Spring Bean的生命周期是Spring面试热点问题。这个问题即考察对Spring的微观了解,又考察对Spring的宏观认识,想要答好并不容易!本文但愿可以从源码角度入手,帮助面试者完全搞定Spring Bean的生命周期。java
是的,Spring Bean的生命周期只有这四个阶段。把这四个阶段和每一个阶段对应的扩展点糅合在一块儿虽然没有问题,可是这样很是凌乱,难以记忆。要完全搞清楚Spring的生命周期,首先要把这四个阶段紧紧记住。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段。在这四步之间穿插的各类扩展点,稍后会讲。面试
实例化 -> 属性赋值 -> 初始化 -> 销毁app
主要逻辑都在doCreate()方法中,逻辑很清晰,就是顺序调用如下三个方法,这三个方法与三个生命周期阶段一一对应,很是重要,在后续扩展接口分析中也会涉及。框架
源码以下,能证实实例化,属性赋值和初始化这三个生命周期的存在。关于本文的Spring源码都将忽略无关部分,便于理解:源码分析
至于销毁,是在容器关闭时调用的,详见ConfigurableApplicationContext#close()post
经常使用扩展点spa
Spring生命周期相关的经常使用扩展点很是多,因此问题不是不知道,而是记不住或者记不牢。其实记不住的根本缘由仍是不够了解,这里经过源码+分类的方式帮你们记忆。3d
第一大类:影响多个Bean的接口代理
实现了这些接口的Bean会切入到多个Bean的生命周期中。正由于如此,这些接口的功能很是强大,Spring内部扩展也常用这些接口,例如自动注入以及AOP的实现都和他们有关。xml
这两兄弟多是Spring扩展中最重要的两个接口!InstantiationAwareBeanPostProcessor做用于实例化阶段的先后,BeanPostProcessor做用于初始化阶段的先后。正好和第1、第三个生命周期阶段对应。经过图能更好理解:
InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口,严格意义上来看他们不是两兄弟,而是两父子。可是从生命周期角度咱们重点关注其特有的对实例化阶段的影响,图中省略了从BeanPostProcessor继承的方法。
InstantiationAwareBeanPostProcessor extends BeanPostProcessor
InstantiationAwareBeanPostProcessor源码分析:
postProcessBeforeInstantiation调用点,忽略无关代码:
能够看到,postProcessBeforeInstantiation在doCreateBean以前调用,也就是在bean实例化以前调用的,英文源码注释解释道该方法的返回值会替换本来的Bean做为代理,这也是Aop等功能实现的关键点。
postProcessAfterInstantiation调用点,忽略无关代码:
能够看到该方法在属性赋值方法内,可是在真正执行赋值操做以前。其返回值为boolean,返回false时能够阻断属性赋值阶段(continueWithPropertyPopulation = false;)。
关于BeanPostProcessor执行阶段的源码穿插在下文Aware接口的调用时机分析中,由于部分Aware功能的就是经过他实现的!只须要先记住BeanPostProcessor在初始化先后调用就能够了。
第二大类:只调用一次的接口
这一大类接口的特色是功能丰富,经常使用于用户自定义扩展。
第二大类中又能够分为两类:
无所不知的Aware
Aware类型的接口的做用就是让咱们可以拿到Spring容器中的一些资源。基本都可以见名知意,Aware以前的名字就是能够拿到什么资源,例如BeanNameAware能够拿到BeanName,以此类推。调用时机须要注意:全部的Aware方法都是在初始化阶段以前调用的!
Aware接口众多,这里一样经过分类的方式帮助你们记忆。
Aware接口具体能够分为两组,至于为何这么分,详见下面的源码分析。以下排列顺序一样也是Aware接口的执行顺序,可以见名知意的接口再也不解释。
Aware Group1
Aware Group2
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {}
这里涉及到另外一道面试题,ApplicationContext和BeanFactory的区别,能够从ApplicationContext继承的这几个接口入手,除去BeanFactory相关的两个接口就是ApplicationContext独有的功能,这里不详细说明。
Aware调用时机源码分析
详情以下,忽略了部分无关代码。代码位置就是咱们上文提到的initializeBean方法详情,这也说明了Aware都是在初始化阶段以前调用的!
能够看到并非全部的Aware接口都使用一样的方式调用。Bean××Aware都是在代码中直接调用的,而ApplicationContext相关的Aware都是经过BeanPostProcessor#postProcessBeforeInitialization()实现的。
感兴趣的能够本身看一下ApplicationContextAwareProcessor这个类的源码,就是判断当前建立的Bean是否实现了相关的Aware方法,若是实现了会调用回调方法将资源传递给Bean。
至于Spring为何这么实现,应该没什么特殊的考量。也许和Spring的版本升级有关。基于对修改关闭,对扩展开放的原则,Spring对一些新的Aware采用了扩展的方式添加。
BeanPostProcessor的调用时机也能在这里体现,包围住invokeInitMethods方法,也就说明了在初始化阶段的先后执行。
关于Aware接口的执行顺序,其实只须要记住第一组在第二组执行以前就好了。每组中各个Aware方法的调用顺序其实没有必要记,有须要的时候点进源码一看便知。
简单的两个生命周期接口
至于剩下的两个生命周期接口就很简单了,实例化和属性赋值都是Spring帮助咱们作的,可以本身实现的有初始化和销毁两个生命周期阶段。
InitializingBean 对应生命周期的初始化阶段,在上面源码的invokeInitMethods(beanName, wrappedBean, mbd);方法中调用。
有一点须要注意,由于Aware方法都是执行在初始化方法以前,因此能够在初始化方法中放心大胆的使用Aware接口获取的资源,这也是咱们自定义扩展Spring的经常使用方式。
除了实现InitializingBean接口以外还能经过注解或者xml配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。由于这几个方法对应的都是同一个生命周期,只是实现方式不一样,咱们通常只采用其中一种方式。
DisposableBean 相似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法做为入口,实现是经过循环取全部实现了DisposableBean接口的Bean而后调用其destroy()方法 。感兴趣的能够自行跟一下源码。
扩展阅读: BeanPostProcessor 注册时机与执行顺序
注册时机
咱们知道BeanPostProcessor也会注册为Bean,那么Spring是如何保证BeanPostProcessor在咱们的业务Bean以前初始化完成呢?
请看咱们熟悉的refresh()方法的源码,省略部分无关代码:
能够看出,Spring是先执行registerBeanPostProcessors()进行BeanPostProcessors的注册,而后再执行finishBeanFactoryInitialization初始化咱们的单例非懒加载的Bean。
执行顺序
BeanPostProcessor有不少个,并且每一个BeanPostProcessor都影响多个Bean,其执行顺序相当重要,必须可以控制其执行顺序才行。关于执行顺序这里须要引入两个排序相关的接口:PriorityOrdered、Ordered
PriorityOrdered是一等公民,首先被执行,PriorityOrdered公民之间经过接口返回值排序,Ordered是二等公民,而后执行,Ordered公民之间经过接口返回值排序
都没有实现是三等公民,最后执行。
在如下源码中,能够很清晰的看到Spring注册各类类型BeanPostProcessor的逻辑,根据实现不一样排序接口进行分组。优先级高的先加入,优先级低的后加入。
根据排序接口返回值排序,默认升序排序,返回值越低优先级越高。
/** * Useful constant for the highest precedence value. * @see java.lang.Integer#MIN_VALUE */ int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; /** * Useful constant for the lowest precedence value. * @see java.lang.Integer#MAX_VALUE */ int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
PriorityOrdered、Ordered接口做为Spring整个框架通用的排序接口,在Spring中应用普遍,也是很是重要的接口。
Spring Bean的生命周期分为四个阶段和多个扩展点。扩展点又能够分为影响多个Bean和影响单个Bean。整理以下:
四个阶段
多个扩展点
影响多个Bean
影响单个Bean
Aware
生命周期