当前位置: 首页 > news >正文

Spring IOC核心详解:掌握控制反转与依赖注入

文章目录

  • 前言
  • 一、IOC核心思想
  • 二、IOC容器实现
    • 1.核心接口:
    • 2.XML配置范例
  • 三、Bean管理实践
    • 1.创建对象
      • (1)基于xml方式创建对象
      • (2)用注解的方式创建对象
    • 2.依赖注入
      • (1)基于xml方式注入属性
        • 基础类型注入
        • 集合类型注入
        • 对象引用注入
      • (2)用注解的方式注入属性
        • 基础类型注入
        • 集合类型注入
        • 对象关系注入
      • (3)配置方式关键对比表
  • 四、IOC优势总结
  • 总结


前言

在传统软件开发中,对象间的依赖关系往往通过硬编码实现:类A直接实例化类B,形成紧密的代码耦合。这种模式导致系统难以维护、扩展困难,且单元测试复杂度陡增。
Spring的IOC(控制反转) 正是为解决这一问题而生。


一、IOC核心思想

传统开发痛点:对象间强耦合(A类直接new B类对象)
解决方案:工厂模式+反射机制+XML解析,实现控制权反转

二、IOC容器实现

1.核心接口:

  • BeanFactory:延迟加载(使用时创建对象)
  • ApplicationContext:立即加载(推荐使用)
// 基础容器(延迟加载)
BeanFactory factory = new XmlBeanFactory(resource);
// 增强容器(立即加载)
ApplicationContext context = 
    new ClassPathXmlApplicationContext("applicationContext.xml");

2.XML配置范例

<!-- 创建对象 -->
<bean id="userService" class="com.example.UserServiceImpl"/>

<!-- 依赖注入 -->
<bean id="dataSource" class="com.example.DruidDataSource">
    <property name="url" value="jdbc:mysql://localhost:3306/db"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>

三、Bean管理实践

1.创建对象

(1)基于xml方式创建对象

核心配置语法:

<!-- 基础对象定义 -->
<bean id="userService" class="com.example.UserServiceImpl"/>

<!-- 带初始化参数的构造器 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <constructor-arg name="url" value="jdbc:mysql://localhost:3306/db"/>
</bean>

关键要素解析:

  1. id:Bean的唯一标识符(IOC容器中的对象名称)
  2. class:全限定类名(包名+类名)
  3. 默认机制:调用无参构造器实例化对象

默认示例:

<!-- 服务层Bean -->
<bean id="orderService" class="com.service.OrderServiceImpl"/>

<!-- DAO层Bean -->
<bean id="userDao" class="com.dao.UserDaoImpl"/>

(2)用注解的方式创建对象

Spring核心注解映射表

注解适用场景等效XML配置
@Component通用组件声明<bean class="完整类路径"/>
@Service业务逻辑层组件<bean id="service".../>
@Repository数据持久层组件<bean id="dao".../>
@Controller表现层控制器<bean id="controller".../>

注解特性说明:

  1. 四者本质都是@Component的特殊化形式
  2. 默认Bean命名规则:首字母小写的类名(如UserServiceImpluserServiceImpl
  3. 可通过注解value属性自定义Bean名称(例:@Service("orderService")

实现步骤:

<context:component-scan base-package="com.example"/>

开启组件扫描

@Service("orderService") // 自定义Bean名称
public class OrderServiceImpl implements OrderService {
    // 类实现
}

最佳实践:

  • 明确分层使用特定注解(如@Service用于服务层)
  • 默认Bean名称为类名首字母小写(如UserDaoImpl→userDaoImpl)
  • 需要配合@ComponentScan注解或XML配置开启扫描

2.依赖注入

(1)基于xml方式注入属性

基础类型注入
<bean id="config" class="com.example.AppConfig">
    <property name="maxThread" value="200"/>
    <property name="timeout" value="5000"/>
</bean>
集合类型注入
<bean id="collectionBean" class="com.example.CollectionDemo">
    <!-- 数组注入 -->
    <property name="ips">
        <array>
            <value>192.168.1.1</value>
            <value>10.0.0.1</value>
        </array>
    </property>

    <!-- Map注入 -->
    <property name="settings">
        <map>
            <entry key="env" value="prod"/>
            <entry key="version" value="1.2.0"/>
        </map>
    </property>

    <!-- 对象引用集合 -->
    <property name="services">
        <list>
            <ref bean="userService"/>
            <ref bean="orderService"/>
        </list>
    </property>
</bean>
对象引用注入
<bean id="userService" class="com.service.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.dao.UserDaoImpl"/>

(2)用注解的方式注入属性

基础类型注入
@Service
public class PaymentService {
    @Value("${payment.timeout:300}") // 带默认值的属性注入
    private Integer timeout;
    
    @Value("Alipay") // 直接赋值
    private String defaultMethod;
}
集合类型注入
@Configuration
public class AppConfig {
    @Bean
    public List<String> whiteList() {
        return Arrays.asList("192.168.1.1", "10.0.0.1");
    }
}

@Service
public class SecurityService {
    @Autowired
    private List<String> whiteList; // 自动注入集合
}
对象关系注入
@Service
public class OrderService {
    // 按类型自动装配(推荐方式)
    @Autowired
    private UserDao userDao;

    // 精确指定Bean名称
    @Autowired
    @Qualifier("clusterUserDao")
    private UserDao backupDao;

    // 构造器注入(不可变依赖推荐)
    private final PaymentService paymentService;
    
    @Autowired
    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

(3)配置方式关键对比表

特性XML配置注解方式
可读性集中配置,结构层级清晰配置分散在代码中,需结合代码阅读
维护性修改配置需重新编译部署配置与代码共存,修改即时生效
灵活性支持热更新,运行时动态调整需重新编译生效
复杂配置擅长处理多对象嵌套关系适合简单直接的配置
适用场景第三方组件集成/历史遗留系统改造现代Spring应用/自主开发组件管理

对比说明

  1. 混合配置策略推荐:核心业务组件使用注解,基础设施配置使用XML
  2. 注解方式编译时验证更严格,能提前发现配置错误
  3. XML支持placeholder动态替换,适合环境差异配置
  4. 注解驱动开发效率更高,符合现代编程习惯

四、IOC优势总结

  • 解耦:对象创建权交给容器
  • 可维护:统一管理依赖关系
  • 易测试:轻松替换Mock对象
  • 扩展性强:方便集成其他框架

总结

IOC不仅是框架特性,更代表了软件设计的哲学转变。掌握其精髓,开发者将能构建出真正面向变化的弹性系统,在快速迭代的数字化时代保持技术竞争力。通过深入理解对象创建和依赖注入的多种实现方式,开发者可以根据具体场景灵活选择最合适的配置策略,构建出既灵活又易于维护的Spring应用程序。

相关文章:

  • (四)---四元数的基础知识-(定义)-(乘法)-(逆)-(退化到二维复平面)-(四元数乘法的导数)
  • 【Spring IoC DI】深入解析 IoC & DI :Spring框架的核心设计思想和 IoC 与 DI 的思想和解耦优势
  • IDEA 快捷键ctrl+shift+f 无法全局搜索内容的问题及解决办法
  • MySQL表的增加、查询、修改、删除的基础操作
  • BEVFormer报错(预测场景与真值场景的sample_token不匹配)
  • springCloud集成tdengine(原生和mapper方式) 其一
  • Springboot之RequestAttributes学习笔记
  • 使用selenium来获取数据集
  • 在Ubuntu 22.04 中安装Docker的详细指南
  • elasticsearch 通用笔记
  • windows 安装 Elasticsearch
  • 六、GPIO中断控制器(1)—— pcf8575
  • CSRF跨站请求伪造(Cross - Site Request Forgery)
  • 蓝桥杯 劲舞团
  • 简要分析IPPROTO_TCP参数
  • 解决Selenium滑动页面到指定元素,点击失效的问题
  • Swagger2 使用教程
  • 为什么 Redis 选择单线程模型?
  • 【3-22 list 详解STL C++ 】
  • RAG知识库的数据方案:图数据库、向量数据库和知识图谱怎么选?
  • 气象干旱黄色预警继续:陕西西南部、河南西南部等地特旱
  • 溢价26.3%!保利置业42.4亿元竞得上海杨浦宅地,楼板价80199元/平方米
  • 第一集|《刑警的日子》很生活,《执法者们》有班味
  • 一热就出汗 VS 热死都不出汗的人,哪个更健康?
  • 酒店取消订单加价卖何以屡禁不绝?专家建议建立黑名单并在商家页面醒目标注
  • 纪念苏联伟大卫国战争胜利80周年阅兵彩排,解放军仪仗队亮相