Spring Bean生命周期
生命周期流程
首先看下生命周期图:
再来一张执行过程:

Spring Bean的生命周期只有四个阶段。要彻底搞清楚Spring的生命周期,首先要把这四个阶段牢牢记住。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。在这四步之间穿插的各种扩展点。
实例化 Instantiation
属性赋值 Populate
初始化 Initialization
销毁 Destruction
实例化 -> 属性赋值 -> 初始化 -> 销毁
主要逻辑都在doCreateBean()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。
createBeanInstance()-> 实例化populateBean()-> 属性赋值initializeBean()-> 初始化
源码如下,能证明实例化,属性赋值和初始化这三个生命周期的存在。关于本文的Spring源码都将忽略无关部分,便于理解:
1  | // 忽略了无关代码  | 
至于销毁,是在容器关闭时调用的,详见ConfigurableApplicationContext#close()
在谈生命周期之前有一点需要先明确:
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
AOP扩展bean生命周期
Spring生命周期相关的常用切入方式非常多,主要有下列方式:
注解方式
在 bean 初始化时会经历几个阶段,首先可以使用注解 @PostConstruct, @PreDestroy 来在 bean 的创建和销毁阶段进行调用。
两个生命周期接口InitializingBean, DisposableBean
还可以实现 InitializingBean, DisposableBean 这两个接口,也是在初始化以及销毁阶段调用。实例化和属性赋值都是Spring帮助我们做的,能够自己实现的就只有 初始化 和 销毁 两个生命周期阶段.
InitializingBean
对应生命周期的初始化阶段,在源码的invokeInitMethods(beanName, wrappedBean, mbd)方法中调用。有一点需要注意,因为
Aware方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用Aware接口获取的资源,这也是我们自定义扩展Spring的常用方式。
除了实现InitializingBean接口之外还能通过注解或者xml配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。DisposableBean
类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其`destroy() 方法;
自定义初始化和销毁方法
也可以自定义方法用于在初始化、销毁阶段调用
实现 Aware 接口
Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源。基本都能够见名知意,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。调用时机需要注意:所有的Aware方法都是在初始化阶段之前调用的!
Aware接口具体可以分为两组。如下排列顺序同样也是Aware接口的执行顺序:
Aware Group1
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
Aware Group2
EnvironmentAware
EmbeddedValueResolverAware 实现该接口能够获取Spring EL解析器,用户的自定义注解需要支持spel表达式的时候可以使用,非常方便。
ApplicationContextAware(ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware) 这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的ApplicationContext对象,因为ApplicationContext是一个复合接口
1  | public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,  | 
这里涉及一道面试题,ApplicationContext 和 BeanFactory的区别,可以从ApplicationContext 继承的这几个接口入手,除去 BeanFactory 相关的两个接口就是ApplicationContext独有的功能.
BeanPostProcessor, InstantiationAwareBeanPostProcessor接口
增强处理器(容器级别),实现 BeanPostProcessor 接口,Spring 中所有 bean 在做初始化时都会调用该接口中的两个方法,, 正因为如此,这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。
这是Spring扩展中最重要的两个接口!
InstantiationAwareBeanPostProcessor作用于实例化阶段的前后;BeanPostProcessor作用于初始化阶段的前后;InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口,严格意义上来看他们是两父子;
Aware调用时机源码分析
详情如下,忽略了部分无关代码。代码位置就是initializeBean方法详情,这也说明了Aware都是在初始化阶段之前调用的!
1  | // 见名知意,初始化阶段调用的方法  | 
可以看到并不是所有的Aware接口都使用同样的方式调用。
- Bean××Aware都是在代码中直接调用的;
 - ApplicationContext相关的Aware都是通过
BeanPostProcessor#postProcessBeforeInitialization()实现的。 
具体流程可以看一下 ApplicationContextAwareProcessor 这个类的源码,就是判断当前创建的Bean是否实现了相关的Aware方法,如果实现了会调用回调方法将资源传递给Bean。
至于Spring为什么这么实现,应该没什么特殊的考量。也许和Spring的版本升级有关。基于对修改关闭,对扩展开放的原则,Spring对一些新的Aware采用了扩展的方式添加。
BeanPostProcessor的调用时机也能在这里体现,包围住 invokeInitMethods 方法,也就说明了在初始化阶段的前后执行。
关于Aware接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了.
实例Demo
User.java
1  | /**  | 
CustomBeanPostProcessor.java
1  | /**  | 
BootStrap.java
1  | /**  | 
运行结果:
1  | 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()函数  | 
总结
Spring Bean的生命周期分为四个阶段和多个扩展点。扩展点又可以分为影响多个Bean和影响单个Bean。整理如下:
四个阶段
- 实例化 Instantiation
 - 属性赋值 Populate
 - 初始化 Initialization
 - 销毁 Destruction
 
多个扩展点
影响多个Bean
- BeanPostProcessor
 - InstantiationAwareBeanPostProcessor
 
影响单个Bean
Aware
Aware Group1
- BeanNameAware
 - BeanClassLoaderAware
 - BeanFactoryAware
 
Aware Group2
- EnvironmentAware
 - EmbeddedValueResolverAware
 - ApplicationContextAware (ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware)
 
生命周期
- InitializingBean
 - DisposableBean