理解 Spring IoC

Spring IoC概述

IoC 全称为 Inversion of Control ,翻译为 “控制反转”。

如何理解“控制反转”好呢?理解好它的关键在于我们需要回答如下四个问题:

  1. 谁控制谁
  2. 控制什么
  3. 为何是反转
  4. 哪些方面反转

通过一个例子可以更方便理解IoC。假设一个人想喝新鲜橙汁,在没有饮品店的日子里,最直观的做法就是:买果汁机和橙子,自己动手制作。值得注意的是:这个过程是自己“主动”创造的过程,也就是说一杯橙汁需要自己创造。这种方法就对应在程序代码中直接 new 一个橙汁对象,橙汁全程由自己制作管理。

然而到了今时今日,由于饮品店的盛行,当想喝橙汁时,第一想法就转换成了找到饮品店的联系方式,通过电话等渠道描述需要、地址、联系方式等,下订单等待,过一会儿就会有人送来橙汁了。在该过程中并没有“主动”去创造橙汁,橙汁是由饮品店创造的,而不是你,然而也完全达到了你的要求,甚至比你创造的要好上那么一些。这个过程饮品店相当于Spring容器,我们获取橙汁对象并不是自己在程序代码中 new 一个对象,而是直接在Spring容器(饮品店)直接获取,饮品店管理橙汁的制作过程。

现在在看上面那四个问题,答案就显得非常明显了:

  1. 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,有了 IoC 容器后,则直接由 IoC 容器来控制。所以“谁控制谁”,当然是 IoC 容器控制对象。
  2. 控制什么:控制对象。
  3. 为何是反转:没有 IoC 的时候我们都是在自己代码中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
  4. 哪些方面反转:所依赖对象的获取被反转。

注入方式

IoC Service Provider为被注入对象提供被依赖对象也有如下几种方式:构造方法注入、setter方法注入、接口注入。

构造方法注入

构造器注入,顾名思义就是被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。

1
2
3
Consumer(OrangeJuice orangeJuice) {
this.orangeJuice = orangeJuice;
}
setter方法注入

对于 JavaBean 对象而言,我们一般都是通过 getter 和 setter 方法来访问和设置对象的属性。所以,当前对象只需要为其所依赖的对象提供相对应的 setter 方法,就可以通过该方法将相应的依赖对象设置到被注入对象中。如下:

1
2
3
4
5
6
7
8
public class Consumer {

private OrangeJuice orangeJuice;

public void setOrangeJuice(OrangeJuice orangeJuice) {
this.orangeJuice = orangeJuice;
}
}

相比于构造器注入,setter 方式注入会显得比较宽松灵活些,它可以在任何时候进行注入(当然是在使用依赖对象之前),

接口注入

接口方式注入带有侵入性,因为它需要被依赖的对象实现不必要的接口,一般都不推荐这种方式。

Spring 体系结构

Resource 体系

org.springframework.core.io.Resource 是对资源的抽象, 不同实现类代表了对不同资源的访问策略,如 ClassPathResource、RLResource、FileSystemResource 等。

ResourceLoader 体系

有了资源,就应该有资源加载,Spring 利用org.springframework.core.io.ResourceLoader来进行统一资源加载,类图如下:

BeanFactory 体系

org.springframework.beans.factory.BeanFactory,是一个非常纯粹的 bean 容器,它是 IoC 必备的数据结构,其中 BeanDefinition 是它的基本结构。BeanFactory 内部维护着一个BeanDefinition map ,并可根据 BeanDefinition 的描述进行 bean 的创建和管理。

  • BeanFactory 有三个直接子类 ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory 。
  • DefaultListableBeanFactory 为默认实现,它实现了所有接口。

BeanDefinition 体系

org.springframework.beans.factory.config.BeanDefinition ,用来描述 Spring 中的 Bean 对象。

BeanDefinitionReader 体系

org.springframework.beans.factory.support.BeanDefinitionReader 的作用是读取 Spring 的配置文件的内容,并将其转换成 Ioc 容器内部的数据结构 :BeanDefinition 。

ApplicationContext 体系

org.springframework.context.ApplicationContext,它叫做应用上下文,是应用层容器。它继承 BeanFactory ,所以它是 BeanFactory 的扩展升级版。由于 ApplicationContext 的结构就决定了它与 BeanFactory 的不同,其主要区别有:

  1. 继承 org.springframework.context.MessageSource 接口,提供国际化的标准访问策略。
  2. 继承 org.springframework.context.ApplicationEventPublisher 接口,提供强大的事件机制。
  3. 扩展 ResourceLoader ,可以用来加载多种 Resource ,可以灵活访问不同的资源。
  4. 对 Web 应用的支持。

总结

本文主要介绍 IoC 的概念,以及 IoC 的三种注入方式,然后介绍了Spring的六大体系,包括Resource、ResourceLoader、BeanFactory、BeanDefinition、BeanDefinitionReader以及ApplicationContext。

参考

  1. 【死磕 Spring】—— IoC 之深入理解 Spring IoC