Spring IOC容器的实现分为两个阶段:1.容器启动阶段 2.Bean的实例化阶段
一.容器初始化阶段
首先通过某种途径加载Configuration MetaData.容器需要依赖某些工具(BeanDefinitionReader)对加载的Configuration MeataData进行解析和分析,并将分析后的信息编组为相应的BeanDefinition。最后将BeanDefinition注册到BeanDefinitionRegistry中。这样容器启动工作就完成了。
二.Bean的实例化阶段
当某个请求方法通过容器的getBean方法明确的请求某个对象,或者因依赖关系容器需要隐式的调用getBean方法时,就会触发Bean的实例化阶段的活动。在本阶段,容器会首先检查所请求的对象之前是否已经初始化,如果没有,则会根据BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。如果该对象实现了某些回调接口,也会根据回调接口的要求来装配它。当对象装配完成之后,容器会立即将其返回请求方使用。bean的实例化过程如下图:
1.实例化bean .
容器内部,采用策略模式来决定采用何种方式初始化bean实例。通常,可以通过反射或者CGLIB动态字节码来初始化相应的bean实例
2.设置对象属性
容器使用BeanWrapper包裹对象实例,并以统一的方式对对象属性进行访问,设置对象属性。
3.检查Aware接口并设置相关依赖
3.1 BeanFactory容器常用的aware接口如下:
(1)BeanFactoryAware:如果对象实现了该接口,BeanFactory容器会将自身设置到当前对象实例
(2)BeanNameAware:如果对象实现了该接口,BeanFactory容器会将加载当前bean的beanName设置到当前对象实例
(3)BeanClassLoaderAware:如果对象实现了该接口,BeanFactory容器会将加载当前bean的Classloader设置到当前对象实例
3.2 ApplicationContext容器常用的aware接口如下:
(1)ResourceLoaderAware:ApplicationContext实现了ResourceLoaderAware接口,当容器检测到对象实现了ResourceLoaderAware接口,会将ApplicationContext设置到当前对象实例中。
(2)ApplicationEventPublisherAware:ApplicationContext实现了ApplicationEventPublisherAware接口,如果对象实现了ApplicationEventPublisherAware接口,当容器检测到对象实现了ApplicationEventPublisherAware接口,会将ApplicationContext设置到当前对象实例中。
(3)ApplicationContextAware:如果对象实现了ApplicationContextAware接口,当容器检测到对象实现了ApplicationContextAware接口,会将ApplicationContext设置到当前对象实例中。
(3)MessageSourceAware:ApplicationContext实现了MessageSourceAware接口,当容器检测到对象实现了MessageSourceAware接口,会将ApplicationContext设置到当前对象实例中。
4.BeanPostProcessor前置处理
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
postProcessBeforeInitialization()方法是图4-10中BeanPostProcessor前置处理这一步将会执行的方法。BeanPostProcessor的两个方法中都传入了原来的对象实例的引用,这为我们扩展容器的对象实例化过程中的行为提供了极大的便利,我们几乎可以对传入的对象实例执行任何的操作。通常比较常见的使用BeanPostProcessor的场景,是处理标记接口实现类,或者为当前对象提供代理实现。
5.检查是否实现了InitializingBean接口以决定是否调用AfterPropertisSet()方法
该接口定义很简单,其作用在于,在对象实例化过程调用过“BeanPostProcessor的前置处理”之后,会接着检测当前对象是否实现了InitializingBean接口,如果是,则会调用其afterPropertiesSet()方法进一步调整对象实例的状态。
6.检查是否配置了自定义的init-method
使用<bean>的init-method属性。通过init-method,系统中业务对象的自定义初始化操作可以以任何方式命名,而不再受制于InitializingBean的afterPropertiesSet()。如果系统开发过程中规定:所有业务对象的自定义初始化操作都必须以init()命名,为了省去挨个<bean>的设置init-method这样的烦琐,我们还可以通过最顶层的<beans>的default-init-method统一指定这一init()方法名。
7.BeanPostProcessor后置处理
postProcessAfterInitialization()则是BeanPostProcessor后置处理那一步将会执行的方法。
8.注册必要的Destruction相关回调接口
容器将检查singleton类型的bean实例,看其是否实现了org.springframework.beans.factory.DisposableBean接口。或者其对应的bean定义是否通过<bean>的destroy-method属性指定了自定义的对象销毁方法。如果是,就会为该实例注册一个用于对象销毁的回调(Callback),以便在这些singleton类型的对象实例销毁之前,执行销毁逻辑。
对于BeanFactory容器来说,我们需要在独立应用程序的主程序退出之前,或者其他被认为是合
适的情况下(依照应用场景而定),调用ConfigurableBeanFactory提供的destroySingletons()方法销毁容器中管理的所有singleton类型的对象实例。
对于ApplicationContext容器来说,AbstractApplicationContext为我们提供了registerShutdownHook()方法,该方法底层使用标准的Runtime类的addShutdownHook()方
式来调用相应bean对象的销毁逻辑,从而保证在Java虚拟机退出之前,这些singtleton类型的bean对象
实例的自定义销毁逻辑会被执行。