文章目录


1、spring bean宏观分析生命周期

对于能够详细介绍spring bean生命周期的同学,基本上在面试的时候,会是一个很大的加分项, 下面我们就逐步分析生命周期的流程,从大角度分析阶段,小角度分析源码,来详细学习一下spring bean的生命周期

(1)生命周期四个阶段

spring生命周期从大的角度来说,就是四个大节点,​​实例化 -> 属性赋值 -> 初始化 -> 销毁​​的过程,其中穿插的各种各样的知识点、扩展点柔和在一起,从而使分析源码的过程逐渐复杂化,所以刚开始我们先整理清楚大致的生命周期经历的阶段。实例化和属性赋值对应构造方法和setter方法的注入,初始化和销毁是用户能自定义扩展的两个阶段

【Spring源码分析】3、Spring Bean 生命周期源码案例分析(面试热点)_生命周期

(2)完整生命周期流程图


  • BeanPostProcessor相关:黄色标识
  • Bean内部相关:白色标识
  • Aware相关:蓝色标识
  • 其他相关类,采用不同的颜色区分

【Spring源码分析】3、Spring Bean 生命周期源码案例分析(面试热点)_生命周期_02

(3)接口方法分类

从第二步中可以看出,调用的方法非常多,这个图并不是所有调用的方法都列举出来了,上面的方法为典型调用的方法, 后面的扩展点分析会讲到其他方法的调用,以及时机

分类类型

作用范围

相关方法

Bean自身的方法

单个Bean

配置文件中的init-method和destroy-method配置的方法、Bean对象自己调用的方法

Bean级接口方法

单个Bean

BeanNameAware、BeanFactoryAware、InitializingBean、DiposableBean等接口中的方法

容器级接口方法

多个Bean

InstantiationAwareBeanPostProcessor、BeanPostProcessor等后置处理器实现类中重写的方法

针对BeanPostProcessor接口的实现类,在spring源码中查看,有非常多,那么问题来了,他们之间的执行顺序是怎么管理的?

【Spring源码分析】3、Spring Bean 生命周期源码案例分析(面试热点)_生命周期_03

BeanPostProcessor有很多个,而且每个BeanPostProcessor都影响多个Bean,其执行顺序至关重要,必须能够控制其执行顺序才行。关于执行顺序这里需要引入两个排序相关的接口​​PriorityOrdered​​、​​Ordered​​,之后会详细分析排序接口的原理,本篇文章主要分析Spring Bean 生命周期

2、spring bean生命周期源码分析

(1)doCreateBean方法分析

spring bean生命周期的核心入口是​​AbstractAutowireCapableBeanFactory.doCreateBean()​​​方法,spring源码中,真正做事的是do开头方法,这里我从​​createBean()​​方法开始分析源码,然后分析执行流程的细节

/**
* 实际创建指定的bean。预创建处理已经发生
* 此时,例如检查{@code postProcessBeforeInstantiation}回调。
* <p>区分默认的bean实例化和使用
* 工厂方法,并自动装配构造函数。
*
* @param beanName bean的名称
* @param mbd 合并bean定义
* @param args 用于构造函数或工厂方法调用的显式参数
* @return Bean的新实例
* @throws BeanCreationException 如果无法创建该bean
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// 实例化bean。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// 允许后处理器修改合并的bean定义。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 应用合并BeanDefinition后置处理器
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

//强烈地缓存单例,以便能够解析循环引用
//即使由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));
}

// 初始化bean实例。
Object exposedObject = bean;
try {
//属性赋值
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
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);
}
}

// 处理循环依赖
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

// 必要时注册一次性Bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

将上面的源码分析成中文结构,这样有利于理解相关方法的使用和调用结果

AbstractBeanFactory
AbstractAutowireCapableBeanFactory.createBean():
实现createBean方法:此类的中央方法:创建一个bean实例,填充该bean实例,应用后处理器等。
(1)AbstractBeanFactory.resolveBeanClass():
为指定的bean定义解析bean类,将bean类名称解析为Class引用(如果需要)并将解析后的Class存储在bean定义中以供进一步使用。
(2)AbstractBeanDefinition.prepareMethodOverrides():
验证并准备为此bean定义的方法替代。检查是否存在具有指定名称的方法。
(3)resolveBeforeInstantiation():
应用实例化之前的后处理器,以解决指定bean的实例化快捷方式。
(4)doCreateBean():
实际创建指定的bean。预创建处理已经发生此时,例如检查{@code postProcessBeforeInstantiation}回调。 <p>区分默认的bean实例化和使用工厂方法,并自动装配构造函数。
【实例化】
(1)如果当前beanDefinition是单例,删除factoryBeanInstanceCache记录,并创建bean实例
createBeanInstance():
创建bean实例
(2)允许后处理器修改合并的bean定义
applyMergedBeanDefinitionPostProcessors():
应用合并BeanDefinition后置处理器
(3)强烈地缓存单例,以便能够解析循环引用,即使由BeanFactoryAware之类的生命周期接口触发。
如果当前是(循环引用):beanDefinition是单例 && 尝试解析Bean之间的循环引用 && 单例bean当前正在创建中
addSingletonFactory():
添加给定的单例工厂以构建指定的单例如有必要。
(4)【属性赋值】
populateBean():属性赋值
(5)【初始化】
initializeBean():初始化bean
(6)如果是(循环引用),则处理循环引用的注入
(7)必要时注册一次性Bean
AbstractBeanFactory.registerDisposableBeanIfNecessary():
将给定的bean添加到该工厂的一次性bean列表中,册其DisposableBean接口和/或给定的destroy方法在工厂关闭时调用(如果适用)。仅适用于单例。

通过以上分析之后,初步得出了spring bean生命周期的前三个阶段,严格意义上说,生命周期还穿插了很多的细节知识点,后面我们再逐一分析使用阶段,以及使用方法

(2)doClose方法分析

接下来分析四大阶段的最后一个阶段,销毁,入口为​​ConfigurableApplicationContext#close()​​​方法, 主要读取的相关源码为​​AbstractApplicationContext.doClose()​​方法,这个方法主要涉及取消注册、发布关闭、停止生命周期、清理bean等操作

/**
*实际执行上下文关闭:发布ContextClosedEvent并
*销毁此应用程序上下文的bean工厂中的单例。
* <p>由{@code close()}和JVM关闭钩子(如果有)调用。
* @see org.springframework.context.event.ContextClosedEvent
* @see #destroyBeans()
* @see #close()
* @see #registerShutdownHook()
*/
protected void doClose() {
// 检查是否需要实际的关闭尝试...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}

// 取消注册应用程序上下文
LiveBeansView.unregisterApplicationContext(this);

try {
// 发布关闭事件。
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}

// 停止所有Lifecycle bean,以避免在单个销毁期间造成延迟。
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}

// 销毁上下文的BeanFactory中所有缓存的单例。
destroyBeans();

// 关闭此上下文本身的状态。
closeBeanFactory();

// 如果希望的话,让子类做一些最后的清理...
onClose();

// 将本地应用程序侦听器重置为预刷新状态。
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// 切换为非活动状态。
this.active.set(false);
}
}

3、spring bean生命周期执行案例

执行案例根据上面的详细流程图来进行分解,需要测试的类有如下几个,和bean本身相关的initMethod指定方法,destroyMethod指定方法


  • 1、BeanFactoryPostProcessor
  • 2、BeanPostProcessor
  • 3、InstantiationAwareBeanPostProcessor
  • 4、BeanNameAware
  • 5、BeanFactoryAware
  • 6、ApplicationContextAware(流程图上没有,但是非常常用)
  • 7、InitializingBean
  • 8、DisposableBean

(1)自定义Bean,实现Aware相关接口、Bean相关接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
* @author Tellsea
* @date 2020-8-14
*/
public class PersonBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware,
InitializingBean, DisposableBean {

private String name;
private int age;

/**
* 实现了BeanNameAware接口,Spring可以将BeanName注入该属性中
*/
private String beanName;
/**
* 实现了BeanFactory接口,Spring可将BeanFactory注入该属性中
*/
private BeanFactory beanFactory;
/**
* 实现了ApplicationContextAware接口,Spring可将ApplicationContext注入该属性中
*/
private ApplicationContext applicationContext;


public PersonBean() {
System.out.println("【Bean构造方法】Person类的无参构造方法");
}

public String getName() {
return name;
}

public void setName(String name) {
System.out.println("【set注入】注入学生的name属性");
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
System.out.println("【set注入】注入学生的age属性");
this.age = age;
}

@Override
public String toString() {
return "PersonBean{" +
"name='" + name + '\'' +
", age=" + age +
", beanName='" + beanName + '\'' +
", beanFactory=" + beanFactory +
", applicationContext=" + applicationContext +
'}';
}

public void myInit() {
System.out.println("【init-method】调用init-method属性配置的初始化方法");
}

public void myDestroy() {
System.out.println("【destroy-method】调用destroy-method属性配置的销毁方法");
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware的setBeanFactory方法得到beanFactory引用");
}

@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("【BeanNameAware接口】调用BeanNameAware的setBeanName方法得到Bean的名称");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
System.out.println("【ApplicationContextAware接口】调用ApplicationContextAware的setApplicationContext方法得到applicationContext:{" + applicationContext + "}");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean接口】调用InitializingBean接口的afterPropertiesSet方法");
}

@Override
public void destroy() throws Exception {
System.out.println("【DisposableBean接口】调用DisposableBean接口的destroy方法");
}
}

(2)自定义BeanFactoryPostProcessor并重写相关方法

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Configuration;

/**
* @author Tellsea
* @date 2020-8-14
*/
@Configuration
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

public MyBeanFactoryPostProcessor() {
System.out.println("【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor实现类构造方法");
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
System.out.println("【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor接口的postProcessBeanFactory方法");
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("personBean");
beanDefinition.getPropertyValues().addPropertyValue("age", "22");
}
}

(3)自定义BeanPostProcessor并重写相关方法

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;

/**
* @author Tellsea
* @date 2020-8-14
*/
@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

public MyBeanPostProcessor() {
System.out.println("【BeanPostProcessor接口】调用BeanPostProcessor的构造方法");
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【BeanPostProcessor接口】调用postProcessBeforeInitialization方法,这里可对" + beanName + "的属性进行更改。");
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【BeanPostProcessor接口】调用postProcessAfterInitialization方法,这里可对" + beanName + "的属性进行更改。");
return bean;
}
}

(3)自定义InstantiationAwareBeanPostProcessor并重写相关方法

一般情况下,当我们需要实现InstantiationAwareBeanPostProcessor接口时,是通过继承Spring框架中InstantiationAwareBeanPostProcessor接口实现类InstantiationAwareBeanPostProcessorAdapter这个适配器类来简化我们实现接口的工作

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.annotation.Configuration;

import java.beans.PropertyDescriptor;

/**
* @author Tellsea
* @date 2020-8-14
*/
@Configuration
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

public MyInstantiationAwareBeanPostProcessor() {
System.out.println("【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor构造方法");
}

/**
* 实例化Bean之前调用
*/
@Override
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
System.out.println("【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法");
return null;
}

/**
* 实例化Bean之后调用
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInitialization方法");
return bean;
}

/**
* 设置某个属性时调用
*/
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out.println("【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法");
return pvs;
}
}

(4)配置扫描类并注入自定义Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

/**
* @author Tellsea
* @date 2020-8-10
*/
@ComponentScan("cn.tellsea")
public class AppConfig {

@Bean(initMethod = "myInit", destroyMethod = "myDestroy")
public PersonBean personBean() {
PersonBean personBean = new PersonBean();
personBean.setName("Tellsea");
personBean.setAge(21);
return personBean;
}
}

(5)测试类

import cn.tellsea.config.AppConfig;
import cn.tellsea.config.PersonBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @author Tellsea
* @date 2020-8-10
*/
public class AppTest {

public static void main(String[] args) {
System.out.println("容器开始创建....");
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println("容器创建成功....");
PersonBean personBean = applicationContext.getBean(PersonBean.class);
System.out.println("从容器中获得的bean:" + personBean);
applicationContext.close();
System.out.println("IOC容器销毁....");
}
}

(6)测试结果

容器开始创建....
【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor实现类构造方法
【BeanFactoryPostProcessor接口】调用BeanFactoryPostProcessor接口的postProcessBeanFactory方法
【BeanPostProcessor接口】调用BeanPostProcessor的构造方法
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor构造方法
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
【BeanPostProcessor接口】调用postProcessBeforeInitialization方法,这里可对appConfig的属性进行更改。
【BeanPostProcessor接口】调用postProcessAfterInitialization方法,这里可对appConfig的属性进行更改。
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInitialization方法
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
【Bean构造方法】Person类的无参构造方法
【set注入】注入学生的name属性
【set注入】注入学生的age属性
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
【set注入】注入学生的age属性
【BeanNameAware接口】调用BeanNameAware的setBeanName方法得到Bean的名称
【BeanFactoryAware接口】调用BeanFactoryAware的setBeanFactory方法得到beanFactory引用
【ApplicationContextAware接口】调用ApplicationContextAware的setApplicationContext方法得到applicationContext:{org.springframework.context.annotation.AnnotationConfigApplicationContext@5afa04c, started on Fri Aug 14 16:36:40 CST 2020}
【BeanPostProcessor接口】调用postProcessBeforeInitialization方法,这里可对personBean的属性进行更改。
【InitializingBean接口】调用InitializingBean接口的afterPropertiesSet方法
【init-method】调用init-method属性配置的初始化方法
【BeanPostProcessor接口】调用postProcessAfterInitialization方法,这里可对personBean的属性进行更改。
【InstantiationAwareBeanPostProcessor接口】调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInitialization方法
容器创建成功....
从容器中获得的bean:PersonBean{name='Tellsea', age=22, beanName='personBean', beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@2fd66ad3: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,appConfig,myBeanFactoryPostProcessor,myBeanPostProcessor,myInstantiationAwareBeanPostProcessor,personBean]; root of factory hierarchy, applicationContext=org.springframework.context.annotation.AnnotationConfigApplicationContext@5afa04c, started on Fri Aug 14 16:36:40 CST 2020}
【DisposableBean接口】调用DisposableBean接口的destroy方法
【destroy-method】调用destroy-method属性配置的销毁方法
IOC容器销毁....

微信公众号

【Spring源码分析】3、Spring Bean 生命周期源码案例分析(面试热点)_ide_04