IOC
IOC即DI,控制反转与依赖注入。表示的概念都是将对象自身从其依赖关系的管理中解放出来,将这个管理工作的责任交给第三方来完成。在Spring中,这个第三方就是IOC容器:基础版的BeanFactory和升级版的ApplicationContext。IOC容器全面接手了对象依赖关系图的管理工作。
管理工作主要分为两大部分:元数据信息的准备和对象关系图的正式建立。
元数据信息
元数据信息主要是指BeanDefinition,BeanDefinition是对Bean定义的描述数据结构,是IOC容器的关键数据结构。元数据信息的准备过程主要有三步:
- 定位:Resource资源定位(文件、路径、网络等,是BeanDefinition的资源定位)
- 读取与转化:通过各类Reader和Parser将Resource解析为BeanDefinition数据结构
- 注册:将BeanDefinition注册到IOC容器中的HashMap中去
对象依赖关系图的建立
关系图的建立大体有三步:
- 实例化Bean
- 注入设置Bean的属性
- Bean的初始化
IOC容器持有了BeanDefinition后,就可以根据BeanDefinition中的信息在实例化Bean时逐步建立起该Bean的依赖关系图了。这一步与JVM中的类加载中解析阶段有些神似,将BeanDefinition中的“符号引用”解析为实例引用。
建立工作通过getBean()方法触发,会首先实例化该Bean(createBean()方法),然后会对该Bean的属性进行设置(populateBean()方法),此时会向IOC容器再次getBean以获取属性值,依次类推,递归调用,最终建立对象依赖关系图。同时对于对象间的depends-on依赖(顺序依赖,如A依赖B的数据,但是B却由C进行设置,此时A depends-on C)也进行递归的准备。在这个过程中Bean的实例化与依赖关系图的建立是交替扩散式进行的。在Bean的属性均注入完毕以后,调用Bean的初始化方法对Bean进行初始化(initializeBean()方法)。
在IOC中,Bean的实例化有两种方式:一种是通过反射的构造函数实例化;一种是通过CGLIB实例化Proxy。通过CGLIB实例化的通常是设置了BeanPostProcessor,或者有lookup method/replace method,需要通过代理技术来实现。
对于Bean属性的注入是通过反射技术来实现的。
Bean生命周期
Spring IOC容器在对Bean的生命周期进行管理时提供了Bean生命周期各个时间点的回调。
Bean的生命周期:
- Bean实例的创建(getBean->createBean)
- 为Bean实例设置属性(populateBean)
- 初始化Bean(initializeBean)
- Bean 被应用使用
- 容器关闭时,Bean销毁(destoryMethod)
其中Bean的初始化主要依次做了4件事:
- 设定Bean对容器的感知(一系列Aware接口)
- BeanPostProcessorsBeforeInitialization()方法
- 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法,如果指定了init-method,调用init-method
- BeanPostProcessorsAfterInitialization()方法
Spring技术内幕