满嘴都是糖果

IoC

IoC全称Inversion of Control ,翻译过来是控制反转,也可以将其称之为依赖注入。

IoC容器充当IoC Service Provider在这里的角色。从被注入对象的角度看,与之前直接寻求依赖对象相比,依赖对象的取得方式发生了反转,控制也从被注入对象转到了IoC Service Provider那里 。

Spring提供了两种容器类型: BeanFactory和ApplicationContext。

BeanFactory

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的一生

容器启动之后,并不会马上就实例化相应的bean定义。我们知道,容器现在仅仅拥有所有对象的BeanDefinition来保存实例化阶段将要用的必要信息。 只有当请求方通过BeanFactory的getBean()方法来请求某个对象实例的时候,才有可能触发Bean实例化阶段的活动。

容器在内部实现的时候,采用“策略模式(Strategy Pattern)”来决定采用何种方式初始化bean实例。通常,可以通过反射或者CGLIB动态字节码生成来初始化相应的bean实例或者动态生成其子类。

org.springframework.beans.factory.support.InstantiationStrategy定义是实例化策略的抽象接口,其直接子类SimpleInstantiationStrategy实现了简单的对象实例化功能,可以通过反射来实例化对象实例,但不支持方法注入方式的对象实例化。 CglibSubclassingInstantiationStrategy继承了SimpleInstantiationStrategy的以反射方式实例化对象的功能,并且通过CGLIB的动态字节码生成功能,该策略实现类可以动态生成某个类的子类,进而满足了方法注入所需的对象实例化需求。默认情况下,容器内部采用的是CglibSubclassingInstantiationStrategy

实例化Bean

容器根据相应bean定义的BeanDefintion取得实例化信息,结合CglibSubclassingInstantiationStrategy以及不同的bean定义类型,就可以返回实例化完成的对象实例。但是并不直接返回实例化的对象,而是以BeanWrapper对构造完成的对象实例进行包裹,返回相应的BeanWrapper实例。 使用BeanWrapper对bean实例操作很方便,可以免去直接使用Java反射API操作对象实例的烦琐。

各色Aware接口

当对象实例化完成并且相关属性以及依赖设置完成之后, Spring容器会检查当前对象实例是否实现了一系列的以Aware命名结尾的接口定义。

  1. org.springframework.beans.factory.BeanNameAware。如果Spring容器检测到当前对象实例实现了该接口,会将该对象实例的bean定义对应的beanName设置到当前对象实例。
  2. org.springframework.beans.factory.BeanClassLoaderAware。如果容器检测到当前对象实例实现了该接口,会将对应加载当前bean的Classloader注入当前对象实例。默认会使用加载org.springframework.util.ClassUtils类的Classloader。
  3. org.springframework.beans.factory.BeanFactoryAware。在介绍方法注入的时候,我们提到过使用该接口以便每次获取prototype类型bean的不同实例。如果对象声明实现了BeanFactoryAware接口, BeanFactory容器会将自身设置到当前对象实例。这样,当前对象实例就拥有了一个BeanFactory容器的引用,并且可以对这个容器内允许访问的对象按照需要进行访问。
BeanPostProcessor

BeanPostProcessor的概念容易与BeanFactoryPostProcessor的概念混淆。但只要记住BeanPostProcessor是存在于对象实例化阶段,而BeanFactoryPostProcessor则是存在于容器启动阶段

BeanPostProcessor接口声明了两个方法,BeanPostProcessor会处理容器内所有符合条件的实例化后的对象实例

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
InitializingBean和init-method

InitializingBean是容器内部广泛使用的一个对象生命周期标识接口 ,用于调整对象实例的状态 ,比如,在有些情况下,某个业务对象实例化完成后,还不能处于可以使用状态。

void afterPropertiesSet() throws Exception;

虽然该接口在Spring容器内部广泛使用,但如果真的让我们的业务对象实现这个接口,则显得Spring容器比较具有侵入性。所以, Spring还提供了另一种方式来指定自定义的对象初始化操作,那就是在XML配置的时候,使用的`init-method`属性。

DisposableBean与destroy-method

为该实例注册一个用于对象销毁的回调 ,以便在这些singleton类型的对象实例销毁之前,执行销毁逻辑。