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

40岁开始学Java:控制反转IoC

在 Java 中,控制反转(Inversion of Control, IoC) 是一种设计原则,其核心思想是:将对象的创建和管理权从代码自身转移到外部容器或框架。通过 IoC,可以降低代码的耦合性,提高模块的复用性和可测试性。
在这里插入图片描述


一、IoC 的核心概念

  1. 谁控制谁?
    • 传统编程中,代码主动创建对象并管理依赖(控制权在代码手中)。
    • IoC 中,对象由外部容器(如 Spring IoC 容器)创建和管理(控制权被反转到容器)。

  2. 为什么需要 IoC?
    • 解耦对象之间的依赖关系,避免硬编码具体实现类。
    • 提高代码的可维护性和可测试性(例如通过替换依赖的模拟对象进行单元测试)。


在这里插入图片描述

二、IoC 的实现方式

1. 通过接口抽象依赖

• 定义接口,让具体实现类依赖于接口而非具体类。

public interface DataSource {
    Connection getConnection();
}

public class MySQLDataSource implements DataSource {
    @Override
    public Connection getConnection() {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/test");
    }
}

在这里插入图片描述

2. 依赖注入(DI)

• IoC 的具体实现方式通常是 依赖注入(DI),即容器负责将依赖对象注入到目标类中。
• DI 的常见方式包括:构造器注入、Setter 注入、字段注入

3. 外部容器管理对象生命周期

• 容器负责对象的创建、初始化、销毁等操作,而不是代码自己 new 对象。


在这里插入图片描述

三、Spring 框架中的 IoC 实现

1. 标记组件

• 使用 @Component(或其他 stereotype 注解,如 @Service, @Repository)标记需要被管理的类。

@Component
public class UserService {
    // 依赖注入...
}
2. 配置依赖关系

方式一:基于 XML 的配置(传统方式)
```xml


 <bean id="dataSource" class="com.example.MySQLDataSource"/>
 ```

方式二:基于 Java 配置类(推荐)
```java
@Configuration
public class AppConfig {

     @Bean
     public DataSource dataSource() {
         return new MySQLDataSource();
     }

     @Bean
     public UserService userService(DataSource dataSource) {
         return new UserService(dataSource);
     }
 }
 ```

方式三:基于注解(最简洁)
```java
@Component
public class UserService {
private final DataSource dataSource;

     @Autowired
     public UserService(DataSource dataSource) {
         this.dataSource = dataSource;
     }
 }
 ```
3. 获取容器并使用对象
public class Main {
    public static void main(String[] args) {
        // 创建 Spring 容器
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        
        // 从容器中获取对象
        UserService userService = context.getBean(UserService.class);
        userService.doSomething();
    }
}

四、IoC 的工作原理

  1. 扫描组件
    • 容器扫描所有被 @Component 或相关注解标记的类,将其注册为“bean”。

  2. 依赖解析
    • 当容器创建某个 bean 时,自动解析其依赖关系(例如构造函数参数、@Autowired 字段),并将对应依赖的 bean 注入。

  3. 生命周期管理
    • 容器控制 bean 的生命周期(如初始化、销毁),可通过 @PostConstruct@PreDestroy 注解定义回调方法。


五、IoC 的优势

  1. 解耦代码
    • 业务类不再直接依赖具体实现类,只需依赖接口。

    // 未使用 IoC 时
    public class UserService {
        private DataSource dataSource = new MySQLDataSource();
    }
    
    // 使用 IoC 后
    public class UserService {
        private final DataSource dataSource; // 由容器注入
    }
    
  2. 易于替换依赖
    • 无需修改业务代码,只需更换容器中的配置即可切换依赖实现。

    // 切换数据源只需修改配置,无需改动 UserService 类
    @Bean
    public DataSource dataSource() {
        return new PostgreSQLDataSource();
    }
    
  3. 便于单元测试
    • 通过容器注入模拟对象(Mock),隔离被测类与真实依赖。

    @Test
    void testUserService() {
        DataSource mockDataSource = Mockito.mock(DataSource.class);
        UserService userService = new UserService(mockDataSource);
        // 验证逻辑...
    }
    

六、IoC vs. DI

IoC 是一种设计思想,强调控制权的转移。
DI 是 IoC 的一种具体实现方式,通过注入依赖来实现控制反转。
Spring 框架 是 IoC 的典型实现,但 IoC 并非 Spring 独有(例如 Guice、PicoContainer 等框架也支持)。


七、总结

通过 IoC 和 Spring 框架,可以实现以下目标:

  1. 集中管理对象:所有对象的创建和依赖由容器统一控制。
  2. 减少重复代码:避免手动编写对象创建和依赖注入逻辑。
  3. 提高可维护性:修改依赖时无需改动业务代码。
  4. 支持 AOP、事务管理等高级功能:基于 IoC 的扩展能力。

如果希望深入理解,可以尝试在 Spring Boot 项目中实践上述示例,并观察容器如何自动管理对象的生命周期。


http://www.kler.cn/a/579104.html

相关文章:

  • 蓝桥备赛(13)- 链表和 list(上)
  • vue3组合式API怎么获取全局变量globalProperties
  • 统信UOS上AI辅助绘图:用DeepSeek+draw.io生成流程图
  • 可狱可囚的爬虫系列课程 18:成都在售新房数据爬虫(lxml 模块)实战
  • 在PyCharm开发环境中,如何建立hello.py文件?
  • Manus全球首个通用Agent,Manus AI:Agent应用的ChatGPT时刻
  • 计算机网络笔记(二)——1.2互联网概述
  • Dify使用日常:我是如何按标题级别将word中的内容转存到excel中的
  • 八点八数字科技:开启数字人应用的无限可能
  • 什么是时序数据库?有哪些时序数据库?常见的运用场景有哪些?
  • nlp培训重点-5
  • DeepSeek【部署 03】客户端应用ChatBox、AnythingLLM及OpenWebUI部署使用详细步骤
  • MySQL数据库安装篇
  • DR和BDR的选举规则
  • NLTK和jieba
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之功能优化,加载结合分页 ,Table11加载结合分页
  • Git与GitHub:理解两者差异及其关系
  • 【HeadFirst系列之HeadFirst设计模式】第18天之蝇量模式(Flyweight Pattern):优化资源的秘密武器
  • 深入了解Linux —— git三板斧
  • Nacos学习笔记-占位符读取其他命名空间内容