IoC全称Inversion of Control ,翻译过来是控制反转,也可以将其称之为依赖注入。
IoC容器充当IoC Service Provider在这里的角色。从被注入对象的角度看,与之前直接寻求依赖对象相比,依赖对象的取得方式发生了反转,控制也从被注入对象转到了IoC Service Provider那里 。
Spring提供了两种容器类型: BeanFactory和ApplicationContext。
BeanFactory作为一个IoC Service Provider,为了能够明确管理各个业务对象以及业务对象之间的依赖绑定关系,同样需要某种途径来记录和管理这些信息。
BeanFactory只是一个接口,我们最终需要一个该接口的实现来进行实际的Bean的管理, DefaultListableBeanFactory就是这么一个比较通用的BeanFactory实现类。 DefaultListableBeanFactory除了间接地实现了BeanFactory接口,还实现了BeanDefinitionRegistry接口,该接口才是在BeanFactory的实现中担当Bean注册管理的角色。
采用外部配置文件时, Spring的IoC容器有一个统一的处理方式。通常情况下,需要根据不同的外部配置文件格式,给出相应的BeanDefinitionReader实现类,由BeanDefinitionReader的相应实现类负责将相应的配置文件内容读取并映射到BeanDefinition,然后将映射后的BeanDefinition注册到一个BeanDefinitionRegistry,之后, BeanDefinitionRegistry即完成Bean的注册和加载。
Spring提供了一种叫做BeanFactoryPostProcessor
的容器扩展机制。 该机制允许我们在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做相应的修改。这就相当于在容器实现的第一阶段最后加入一道工序,让我们对最终的BeanDefinition做一些额外的操作 。
容器启动之后,并不会马上就实例化相应的bean定义。我们知道,容器现在仅仅拥有所有对象的BeanDefinition来保存实例化阶段将要用的必要信息。 只有当请求方通过BeanFactory的getBean()
方法来请求某个对象实例的时候,才有可能触发Bean实例化阶段的活动。
容器在内部实现的时候,采用“策略模式(Strategy Pattern)”来决定采用何种方式初始化bean实例。通常,可以通过反射或者CGLIB动态字节码生成来初始化相应的bean实例或者动态生成其子类。
org.springframework.beans.factory.support.InstantiationStrategy
定义是实例化策略的抽象接口,其直接子类SimpleInstantiationStrategy
实现了简单的对象实例化功能,可以通过反射来实例化对象实例,但不支持方法注入方式的对象实例化。 CglibSubclassingInstantiationStrategy
继承了SimpleInstantiationStrategy
的以反射方式实例化对象的功能,并且通过CGLIB的动态字节码生成功能,该策略实现类可以动态生成某个类的子类,进而满足了方法注入所需的对象实例化需求。默认情况下,容器内部采用的是CglibSubclassingInstantiationStrategy
。
容器根据相应bean定义的BeanDefintion
取得实例化信息,结合CglibSubclassingInstantiationStrategy
以及不同的bean定义类型,就可以返回实例化完成的对象实例。但是并不直接返回实例化的对象,而是以BeanWrapper对构造完成的对象实例进行包裹,返回相应的BeanWrapper实例。 使用BeanWrapper对bean实例操作很方便,可以免去直接使用Java反射API操作对象实例的烦琐。
当对象实例化完成并且相关属性以及依赖设置完成之后, Spring容器会检查当前对象实例是否实现了一系列的以Aware命名结尾的接口定义。
BeanPostProcessor
的概念容易与BeanFactoryPostProcessor
的概念混淆。但只要记住BeanPostProcessor是存在于对象实例化阶段,而BeanFactoryPostProcessor则是存在于容器启动阶段。
BeanPostProcessor接口声明了两个方法,BeanPostProcessor会处理容器内所有符合条件的实例化后的对象实例
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
InitializingBean是容器内部广泛使用的一个对象生命周期标识接口 ,用于调整对象实例的状态 ,比如,在有些情况下,某个业务对象实例化完成后,还不能处于可以使用状态。
void afterPropertiesSet() throws Exception;
虽然该接口在Spring容器内部广泛使用,但如果真的让我们的业务对象实现这个接口,则显得Spring容器比较具有侵入性。所以, Spring还提供了另一种方式来指定自定义的对象初始化操作,那就是在XML配置的时候,使用
为该实例注册一个用于对象销毁的回调 ,以便在这些singleton类型的对象实例销毁之前,执行销毁逻辑。