文章目录
一、前言
同人有生老病死一样,在Spring中IoC容器管理的Bean也具备实例化、初始化、销毁一整套完整的生命周期。有了生命周期,Ioc容器就能在生命周期的各个阶段对Bean的功能进行扩展或增强,比如我们自定义的init方法、destroy方法、以及Aop代理等,都是围绕Bean的生命周期在特定阶段来完成定制化的功能,所以说掌握Spring Bean生命周期是进阶为Spring高阶玩家必须迈出的第一步!
二、Bean的生命周期
通常说Spring Bean的生命周期,指的是Bean的初始化这一步,不过楼主觉得,没有鸡哪来蛋,如【俯瞰Spring】一、Spring核心工作机制,Bean的源头都是从Bean定义开始,故宽泛点来理解,Bean生命周期从Spring容器启动开始,生成Bean定义、实例化、完成依赖注入、初始化,再到最终Spring容器销毁Bean。放张图,直观感受下:
三、Bean生命周期剖析
有了上图的整体印象,我们在针对每个阶段,深入局部窥视下,有图真香!
3.1 Bean定义生成、注册
如第一幅图所示,从Bean定义产生到最终注册Bean定义,中间Spring留了一个扩展点BeanFactoryPostProcessor.postProcessBeanDefinitionRegistry()
用于修改Bean定义;易见,这个扩展点的触发时机是Bean定义加载已完成,但还没开始实例化、初始化之前。
其最最重要的一个实现类是 ConfigurationClassPostProcessor
, 几个重要注解如@Configuration
、@Import
、@Bean
都是由这个类承担的。后续会开文单独介绍,这里不再展开。
3.2 实例化
3.2.1实例化是什么?
所谓实例化,说白了就是new对象呗。如上图所示,Spring有三种方式来new对象:
- 通过FactoryMethod实例化,多用在@Bean;
- 推断出合适的构造方法, 通过构造方法实例化(怎么推断这块有点复杂,先不展开)
- 采用喜闻乐见的无参构造方法
3.2.2 扩展点
在实例化这个阶段的前、后,Spring提供了两处扩展: InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
和 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
InstantiationAwareBeanPostProcessor
比较重要的实现类为AnnotationAwareAspectJAutoProxyCreator
。光从名字就能看出这个类跟生成Aop代理有关,那是不是在这个阶段生成了Aop代理呢?No!记住一点,既然是代理,那必须有被代理的目标对象,皮之不存,毛将焉附!因为这时候目标对象都还不完整,甚至都没被new出来。
存在即合理,Spring的大师搞这个东东肯定有目的。实际上AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation()
做了识别解析Aspect切面,Aop中常用的几个注解:@Around
、@Before
、@After
、@AfterReturning
、@AfterThrowing
就是在这里增强的
3.3 依赖注入
依赖注入这一阶段,就是将对象依赖的属性挨个填充。比如:ControllerA依赖了ServiceB、ServiceC,那么依赖注入干的活就是把ControllerA的两个属性ServiceB、ServiceC都填充好。
Spring的依赖注入主要是InstantiationAwareBeanPostProcessor.postProcessPropertyValues()
这个BeanPostProcessor来完成,细节不展开!
3.4 初始化
初始化,这个阶段细节非常多,也都很重要。如上图那个大框框里面。
-
invokeAwareMethods() 方法
如果发现实例对象是XXXAware实例,则直接强转调用setXXX()方法 -
applyBeanPostProcessorsBeforeInitialization()方法
用到 Spring容器最新核心的扩展接口BeanPostProcessor.postProcessBeforeInitialization()
; 图中楼主特意把ApplicationContextAwareProcessor
和
CommonAnnotationBeanPostProcessor
列举出来:
ApplicationContextAwareProcessor
同XXXAware一样,做了两件比较重要的事:EnvironmentAware.setEnvironment()
和ApplicationContextAware.setApplicationContext()
CommonAnnotationBeanPostProcessor
则处理了@PostConstruct
注解,即我们加上该注解的方法,就是在这里被触发调用的 -
invokeInitMethods() 方法
如果我们的实例是InitializingBean
的实现类,则会被强转触发afterPropertiesSet()
方法
如果我们的实例,有自定义的init方法: 如@Bean自定义的init方法,那么就Spring就会帮我们触发下自定义的init方法 -
applyBeanPostProcessorsAfterInitialization() 方法
楼主单独列了下AbstractAutoProxyCreator
,这家伙的postProcessAfterInitialization()
方法就是用来创建AOP代理的!
3.5 销毁
初始化完成之后,这时候的Bean就是一个有血有肉的Bean,该依赖的都注入了,该触发的init方法也触发了,甚至这个bean还可能已被aop代理狸猫换太子了;不过,有些bean还需要感知到容器关闭,以便在容器关闭时,做一些资源释放(比如: 关闭连接、关闭线程池);这种Bean就需要接受Spring的特殊关注,单独登记起来;实现途径有三种: @PreDestroy
注解的方法、实现 DisposableBean
接口、@Bean指定destroy
方法
四、总结
本文通过2幅图,先整体后局部讲解了Spring Bean的生命周期,相关知识点概括如下:
- Bean的生命周期:包含Bean定义的生成及注册、实例化、依赖注入、初始化、销毁几个阶段
- 修改Bean定义的扩展点: BeanFactoryPostProcessor
- 依赖注入: InstantiationAwareBeanPostProcessor
- 实例化前、后的扩展点: InstantiationAwareBeanPostProcessor(这个类不仅干了依赖注入还参与了实例化)
- 初始化前、后的扩展点: BeanPostProcessor,特别是其实现类 CommonAnnotationBeanPostProcessor 和 AbstractAutoProxyCreator
- Bean的init方法三种实现方式:1、@PostConstruct 注解的方法;2、实现 InitializingBean接口;3、通过xml或@Bean值定init方法
- Bean的destroy方法三种实现方式:1、@PreDestroy 注解的方法;2、实现 DisposableBean 接口;3、通过xml或@Bean指定destroy方法