Spring Bean 的生命周期真的是面试的时候对于 Spring 的最高频的考点之一了,笔者已经被这个问题问懵了不止一次,始终记不住那一大串的步骤,但实际上尝试去死记硬背那些步骤的我是谬误的,外表上看只是背诵一个流程,实际上,这个流程牵扯到的知识点可是很多而且很有意思的。
上面这个图我想很多人应该都看过雷同的或者类似的:
看起来还是挺长的对吧,然而咱们其实能够把它划分成上面四个大的步骤:
- 实例化 Bean
- 设置对象属性,依赖注入
- 初始化
- destroy:bean 的销毁
接下来,我会依据这个步骤,一步步的解说相干的知识点,从生命周期登程,将 Spring 中重要的类或接口来一一阐明。
一、实例化 Bean
这第一步,容器通过获取 BeanDefinition 对象中的信息进行实例化。并且这一步仅仅是简略的实例化,并未进行依赖注入,能够了解成 new xx()。但要留神的是,对于 BeanFactory 容器和 ApplicationContext 容器它们的实例化是有区别的。
- 对于 BeanFactory 容器,当客户向容器申请一个尚未初始化的 bean 时,或初始化 bean 的时候须要注入另一个尚未初始化的依赖时,容器就会调用 createBean()进行实例化。
- 对于 ApplicationContext 容器,当容器启动完结后,便实例化所有的 bean。
那么既然提到了 BeanFactory 和 ApplicationContext,我就对这两个接口也简略介绍一下。它们别离位于 org.springframework.beans 和org.springframework.context两个包下,而这两个包,正是 Spring IoC 容器的根底。BeanFactory 提供了框架最根底的一些性能,包含 IOC 的配置机制,提供 Bean 的各种定义,建设 Bean 之间的依赖关系等。ApplicationContext 继承了 BeanFactory,因而它领有 BeanFactory 的所有性能,但它自身还继承了一些其余的接口,比方音讯资源配置,事件公布等。
BeanFactory 是 Spring 框架的基础设施,面向 Spring。ApplicationContext 面向 Spring 框架的开发者。所以咱们平时开发的过程中其实也能够发现到,咱们更多的会用上的是 ApplicationContext 相干的工具,而不是 BeanFactory。
除此之外,在实例化这个步骤的前后,实际上还有暗藏工作,牵扯到的接口叫做InstantiationAwareBeanPostProcessor。它继承了BeanPostProcessor。可能有的人不晓得 BeanPostProcessor 这个接口,那么我就先介绍下这个。
BeanPostProcessor也是位于 org.springframework.beans 下,又叫做 后置处理器 ,它定义了一系列的回调办法用来让使用者能够自定义 Bean 实例化或者依赖解析等的逻辑。它自身只有两个办法: postProcessBeforeInitialization 和 postProcessAfterInitialization。如办法名所说,定义 Bean 的 初始化 前后的逻辑。这个接口在整个生命周期中都有着关联。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}
不要弄混了 BeanPostProcessor 中的办法我说的是 初始化 前后,而生命周期的第一步是实例化。这里用到的 InstantiationAwareBeanPostProcessor 它有本人的对于实例化逻辑解决的两个办法。postProcessBeforeInstantiation 和 postProcessAfterInstantiation。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {return null;}
}
通过查找调用 postProcessBeforeInstantiation 这个办法的中央,会追溯到创立 Bean 的要害办法。就是 AbstractAutowireCapableBeanFactory 下的 createBean()。
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {// 外面的代码我上面挑出重点的步骤一步步的贴出来}
通过查看源码对于此办法的正文就晓得它有多重要了。它能够创立 Bean 的实例,对其进行属性填充,调用 BeanPostProcesser 等。第一步咱们留神到的代码应该是
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
它实际上是比咱们下面生命周期的图示还要之前的一步,就是获取 BeanDefinition 对象中的信息来对 Bean class 进行解析。所谓BeanDefinition,它就是对于 Bean 的一个形容。它蕴含了 Bean 的一些根底信息,如 Bean 的 name、Bean 的作用域、和其余 Bean 的关系等等。解析完之后再进行到下一步。
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {return bean;}
这个正文其实也给出了它的意义了,它给予 BeanPostProcessor 们一个机会,能够返回一个代理而不是指标 bean 的实例。但咱们翻阅到下面的 InstantiationAwareBeanPostProcessor 对于此办法的实现,会发现它返回的是 null,所以默认的逻辑这里是不会 return 的。所以咱们会走到下一步,doCreateBean。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean'" + beanName + "'");
}
return beanInstance;
进入到这个办法,它的第一行正文也是简略粗犷,就是来实例化 Bean 的。
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);
}
但能够发现,createBeanInstance()这个办法返回的是一个 BeanWrapper 对象。BeanWrapper是对 Bean 的一个包装,它能够设置获取被包装的对象,获取被包装 bean 的属性形容器等。咱们平时开发是不会间接应用这个类的。通过 createBeanInstance()这个办法的正文咱们也能明确,它的作用是对于指定的 bean 生成一个新的实例,这里能够应用适合的实例化策略,比方工厂办法,结构器注入或者简略实例化等。
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 代码我也不贴了}
接下来这段代码,正文也有阐明,就是将调用各种 postProcessers 来进行属性的合并,这里会进行一些注解的扫描。
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
再而后是一段跟一个面试题严密相干的代码,那就是 Spring 如何解决循环依赖。因为本文的重点是讲 bean 的生命周期,原本筹备一起写完的,但写着写着发现要说的太多了,前面我会另外独自写文章来讲述如何解决循环依赖的问题。
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean'" + beanName +
"'to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
二、设置对象属性,依赖注入
完结了实例化之后,咱们持续在 createBean 这个办法上持续往下走,到了 populateBean 这一步。
// Initialize the bean instance.
Object exposedObject = bean;
try {populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
对于这个办法,咱们已开始留神到的就是我之前说过在实例化前后都是存在着暗藏工作,下面提到了实例化之前的 postProcessBeforeInstantiation,那么现在曾经实例化了,当初呈现了实例化之后的办法 postProcessAfterInstantiation,这里也是给 InstantiationAwareBeanPostProcessors 一个机会去自定义属性被赋值后的形式。在前面代码中回去执行这个后置处理器的办法。
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}
}
}
持续往下,咱们能看到一个相熟的单词,Autowire,不过这里是获取以后注入的形式,依据 byName 还是 byType 来取得要注入的属性。这里我也不深刻阐明了。
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
而后就是 populateBean 的第一步我就提到的办法,如果存在后置处理器,那么会进行属性的校验和解决,同时第二个布尔变量是用来判断是否进行依赖校验的。
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {return;}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
最初一步,就是将后面这些步骤失去的属性进行注入了。
if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);
}
三、初始化
populateBean()办法完结后开始进入 initializeBean()办法,正如办法名所表白的,就是 bean 的 初始化。留神初始化和实例化不是一个意思,在生命周期中 bean 是先进行实例化再进行初始化的。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
首先第一步,先不论那些平安机制的代码,咱们要关注的是 invokeAwareMethods(beanName, bean); 这行代码,这里就是调用所有的 Aware 类型的接口。Spring 中 Aware 类型的接口能够让咱们获取容器中的一些资源。
private void invokeAwareMethods(String beanName, Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
比方这外面呈现的有三种 Aware 类型的接口: BeanNameAware, BeanClassLoaderAware,BeanFactoryAware。它们依据 bean 实现了某个接口来实现不同的工作。
- 如果实现了 BeanNameAware 接口,则通过 setBeanName()办法将 beanName 设置给这个 bean
- 如果实现了 BeanClassLoaderAware 接口,则通过 setBeanClassLoader()办法,将 ClassLoader 传入
- 如果实现了 BeanFactoryAware 接口,则通过 setBeanFactory()办法,将 BeanFactory 容器实例传入
完结完 Aware 接口的调用,持续往下走,到了 applyBeanPostProcessorsBeforeInitialization()这个办法(因为 if 判断是这个 bean 是空或者这个 bean 是否是 synthetic 的,就是是否是利用本人定义的,显然咱们本人的 bean 不是,所以 if 条件后半部分会是 true)。这个办法就是解决我之前有提到过的 BeanPostProcessor 的 postProcessBeforeInitialization()办法。如果 Bean 实现了 BeanPostProcessor 接口,那么就会执行这个办法。
之后,流程来到了 invokeInitMethods()这一步,这一步就是执行 bean 的自定义初始化办法。如果 bean 实现了 InitializingBean 接口,就须要重写 afterPropertiesSet() 办法,则 invokeInitMethods 的时候会调用这个重写后的 afterPropertiesSet() 办法,如果 bean 自定义了 init 办法,则会调用指定的 init 办法(可通过 xml 中配置 bean 的 init-method 属性实现),这两个办法的先后顺序是: afterPropertiesSet 在前,自定义 init 在后。
继续下去就是 applyBeanPostProcessorsAfterInitialization()办法了,和后面的 applyBeanPostProcessorsBeforeInitialization()办法前后响应,这个就不用多说了。
四、销毁
前面的一段代码还是跟解决循环依赖有关系,就先不多说,间接到最初一步,registerDisposableBeanIfNecessary().
销毁这一步其实就是能够让咱们本人自定义 bean 的销毁办法,用到的要害的接口是 DisposableBean,它和InitializingBean 接口相似,只是一个初始化阶段的 init,一个是完结阶段的 destroy。
/**
* Add the given bean to the list of disposable beans in this factory,
* registering its DisposableBean interface and/or the given destroy method
* to be called on factory shutdown (if applicable). Only applies to singletons.
* @param beanName the name of the bean
* @param bean the bean instance
* @param mbd the bean definition for the bean
* @see RootBeanDefinition#isSingleton
* @see RootBeanDefinition#getDependsOn
* @see #registerDisposableBean
* @see #registerDependentBean
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {throw new IllegalStateException("No Scope registered for scope name'" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
代码示例
下面一大段一大段的源码可能看着让人有点好受,不如间接写个 demo 轻松一下。因为只是体现一下生命周期,那么咱们的依赖就很简略,spring-context 和 spring-beans 即可。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
咱们先定义一个自定义的后置处理器,为了体现初始化前后和实例化前后的流程,实现 InstantiationAwareBeanPostProcessor 接口,并重写 postProcessBeforeInstantiation()/postProcessAfterInstantiation()/postProcessBeforeInitialization()/postProcessAfterInitialization()这四个办法。
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {System.out.println(beanName + "实例化前");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println(beanName + "实例化后");
return false;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(beanName + "初始化前");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(beanName + "初始化后");
return null;
}
}
再定义一个“惯例”的 Bean,但咱们也为了反馈初始化和销毁的几个操作,让他实现了 InitializingBean, DisposableBean, BeanNameAware 三个接口。并实现对应的办法,Aware 接口这里我就只实现一个了,只是为了体现注入 Aware 接口那个步骤。
public class DemoBean implements InitializingBean, DisposableBean, BeanNameAware {public DemoBean() {System.out.println("demoBean 实例化");
}
@Override
public void afterPropertiesSet() throws Exception {System.out.println("demoBean afterPropertiesSet");
}
public void init() {System.out.println("demoBean init");
}
@Override
public void destroy() throws Exception {System.out.println("demoBean destroy");
}
@Override
public void setBeanName(String s) {System.out.println("BeanNameAware setBeanName:"+ s);
}
}
配置文件很简略,就两个 bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans>
<bean name="myInstantiationAwareBeanPostProcessor" class="cn.leafw.spring.beans.MyInstantiationAwareBeanPostProcessor" />
<bean name="demoBean" class="cn.leafw.spring.beans.DemoBean" init-method="init">
</bean>
</beans>
</beans>
测试类也很简略粗犷,就单纯启动和完结。
public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
applicationContext.registerShutdownHook();}
}
点击运行,接下来就是意料之中的后果输入:
因为属性注入不不便在这外面进行测试,但大家晓得是在实例化和初始化之间就好。所以其实总的来说,Spring 的生命周期了解起来不算很难,但大家对生命周期外面要害的接口或者类要有印象,ApplicationContext 和 BeanFactory 就不必多说,BeanPostProcessor是肯定要晓得的,Spring 中的很多性能的实现都跟其无关。比方 @Autowired 注解的原理,数据校验 Validate 的原理,都是有对应的处理器。
这篇博客写了我挺久的工夫,就是越写发现自己对 Spring 的理解越肤浅,本认为啃完了 Spring 文档的我应该是能轻松看懂源码,但实际上还是有点吃力的,但看懂了之后真的神清气爽,前面还会持续在这个坑里多填一点货色,学到的越多发现不会的越多,一起提高吧。