IOC - 图1

原理

IoC全称Inversion of Control,直译为控制反转.
首先是一个常见的场景,比如我们一共有三个类: BookService, UserService, HistoryService
这三个类都需要执行以下操作

  1. 初始化数据库连接
  2. 查询数据
  3. 返回数据

这就带来了问题,

  1. 实例化一个类的时候会带来冗余的代码,比如初始化数据库连接 。
  2. 组件里面依赖的资源需要进行销毁? 但是这个组件可能又被其他组件依赖,这样依赖很容易出现资源无法销毁的情况
  3. 一个组件里面,实例化太多的组件,依赖关系复杂,不好测试,容易出错

解决方法:
把这些组件的创建,交给系统管理,而不是在类里面实例化组件,而是统一由系统创建,最后由系统销毁

如何做?

  1. Spring里面的 IOC 负责创建组件
  2. IOC 负责根据依赖关系组装组件
  3. IOC 负责销毁和关闭资源

一般有两种方法,一个是通过 set* 方法注入,一个是通过构造函数注入

比如一个查询书籍的 service,首先我们需要依赖数据库,那么我们就注入数据库实例

  1. public class BookService {
  2. private DataSource dataSource;
  3. public void setDataSource(DataSource dataSource) {
  4. this.dataSource = dataSource;
  5. }
  6. }

这个程序不会自己去实例化数据库连接实例,而是通过 setDataBaseSource 把数据库实例给传进来。它解决了一个最主要的问题:将组件的创建+配置与组件的使用相分离,并且,由IoC容器负责管理组件的生命周期。
然后在 XML 中, 我们声明这个依赖关系。

  1. <beans>
  2. <bean id="dataSource" class="HikariDataSource" />
  3. <bean id="bookService" class="BookService">
  4. <property name="dataSource" ref="dataSource" />
  5. </bean>
  6. <bean id="userService" class="UserService">
  7. <property name="dataSource" ref="dataSource" />
  8. </bean>
  9. </beans>

然后 IOC 会根据这个 XML 进行装配,用 Java 代码写出来像这样

DataSource dataSource = new DataSource();
BookService bookService = new BookService();
bookService.setDataSource(dataSource);

只不过 spring 中是通过反射来完成的

另一种方法是通过构造方法进行注入:

public class BookService {
    private DataSource dataSource;

    public BookService(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}