Spring Bean生命周期

1. 简介

Spring核心流程梳理我们介绍了Spring容器的refresh过程,但是我们并没有进入到Spring Bean的创建等生命周期等内容。

这里,就来梳理一下Spring Bean的生命周期。

我们还是关注流程,重点关注核心的入口,忽略具体实现的细节。

目标也很简单:

  1. 知道Spring Bean相关的扩展点,方便我们做自定义和阅读源码
  2. 当遇到问题的时候,能大致了解相关的debug入口

2. Bean处理器

2.1 BeanPostProcessor

在开始之前,先简单聊两句BeanPostProcessor,因为Bean的很多处理过程涉及到它,有点俄罗斯套娃的感觉。

Object postProcessBeforeInitialization(Object bean, String beanName)
Object postProcessAfterInitialization(Object bean, String beanName)

首先要弄清楚什么是Initialization,初始化,才知道是那之前那之后,我们可以做点啥。

初始化,就是我们调用类的实例bean已经创建好了,属性也设置好了。

调用我们自定义的:InitializingBean的afterPropertiesSet,init-method方法的过程。

所以,postProcessBeforeInitialization是在bean的属性设置之后被调用。

然后,afterPropertiesSet,init-method被调用。

最后,postProcessAfterInitialization被调用

2.2 InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor继承了BeanPostProcessor,多添加了下面3个方法:

@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;
}

实例化Instantiation是什么过程呢,简单的来说就是new过程,Spring当然是通过反射完成。

postProcessBeforeInstantiation就是在一个bean new之前被调用。
postProcessAfterInstantiation是在bean new之后被调用。

postProcessProperties这个方法是在这个bean的property和value解析完成之后被调用。

2.3 SmartInstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor继承了InstantiationAwareBeanPostProcessor,又添加了3个方法:

// 探测bean的类型
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

// 选择合适的构造器
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

// 获得早期暴露的bean引用,Spring处理循环引用就用到这个方法
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;

你也可以看看BeanPostProcessor与Spring无侵入扩展这篇文章。

3. AbstractAutowireCapableBeanFactory

如果Spring容器的核心是AbstractApplicationContext,那么Spring Bean相关的流程的核心就是AbstractAutowireCapableBeanFactory。

Bean生命周期最重要的流程就3个:

  1. 实例化(Instantiate):创建实例,相当于new过程
  2. 初始化(Initialize):设置值的过程,相当于setter过程
  3. 销毁:一般不需要,特殊的可以做释放资源等工作

注意:Instantiate和Initialize两个单词咋看很像,但是两个流程还是有很大差别,不要高混淆了

我们从AbstractApplicationContext的refresh方法中可以知道Bean创建的相关流程入口是:finishBeanFactoryInitialization方法。

调用链很长,分支很多,我们直接聚焦到核心的方法:AbstractAutowireCapableBeanFactory的doCreateBean方法。

3.1 doCreateBean方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// 实例化流程,创建bean实例
		BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);

		// 初始化bean实例
		Object exposedObject = bean;
        //设置property value,相当于setter过程
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
		
		// 销毁相关流程
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
		return exposedObject;
	}

上面的方法是伪代码,从原来代码中抽取出核心流程的部分,避免被无关的信息所干扰。

创建bean(new)的流程入口createBeanInstance这里我们暂时不关注,我本只需要知道,现在通过反射我们获取到一个Bean的实例了。

接下来我们来看初始化的流程,首先populateBean,populate是添加输入数据的意思,根据名字我们也能猜出大概是要执行setter方法了。

3.2 populateBean方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // InstantiationAwareBeanPostProcessor是BeanPostProcessor的子类,这里是调用其bean实例化之后的注入接口
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    // 后面是,获取的bean的PropertyValues,解析是否需要自动注入,检查PropertyValues有没有需要预处理等流程
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    
    // 
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

3.3 initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 检查bean是否是BeanNameAware、BeanClassLoaderAware、BeanFactoryAware调用对应方法
    invokeAwareMethods(beanName, bean);

    // 调用BeanPostProcessor的postProcessBeforeInitialization来处理bean
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    
    // 如果bean实现了InitializingBean,调用其afterPropertiesSet,如果有init-method,也会在afterPropertiesSet之后调用
    invokeInitMethods(beanName, wrappedBean, mbd);
    
    // 调用BeanPostProcessor的postProcessAfterInitialization来处理bean
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    return wrappedBean;
}

@PostConstuct并没有在initializeBean处理,而是通过CommonAnnotationBeanPostProcessor、InitDestroyAnnotationBeanPostProcessor实现。

这2个类一看就能猜到是BeanPostProcessor,事实上的确是在InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法中处理。

因为initializeBean是初始化方法,@PostConstuct是在初始化之前执行,所以,调用顺序就能确定了:

  1. @PostConstuct方法
  2. afterPropertiesSet
  3. init-method

initializeBean方法中处理的Aware是:

  1. BeanNameAware给bean设置beanName
  2. BeanClassLoaderAware给bean设置ClassLoader
  3. BeanFactoryAware给bean设置BeanFactory

其他的Aware,通过ApplicationContextAwareProcessor,它是一个BeanPostProcessor,会在bean初始化之前,但是肯定在前面3个之后调用:

  1. EnvironmentAware:设置获取环境属性相关的Enviroment
  2. EmbeddedValueResolverAware:设置SpEL解析器
  3. ResourceLoaderAware:设置资源加载器
  4. ApplicationEventPublisherAware:设置事件发布器
  5. MessageSourceAware:设置国际化相关的MessageSource
  6. ApplicationStartupAware:设置启动指标监控相关的ApplicationStartup
  7. ApplicationContextAware:设置容器本身ApplicationContext

3.4 registerDisposableBeanIfNecessary方法

这个方法咱就不细入了,简单说一下逻辑:

  1. 处理bean中有@PreDestroy注解的方法
  2. 如果实现了DisposableBean接口处理其destroy方法
  3. 检查destroy-method,如:

4. Spring Bean生命周期小结

先看一个简化流程:
Spring bean创建流程

在看一下常规流程逻辑调用链:
Spring Bean创建逻辑调用链

5. 循环依赖

Spring Bean的创建过程中还有一个重要的问题,依赖循环,这里大致说2句。

public class A {
    @Resource
    private B b;
}

public class B {
    @Resource
    private A a;
}

这可咋整哦?

逻辑可以通过的DefaultSingletonBeanRegistry的三级缓存来处理:

// 缓存已经创建完成的bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 缓存ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

// 缓存还未进行依赖注入和初始化方法调用的bean实例
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
		// 如果是单例,并且允许循环引用,并且这个实例正在创建中
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
            //把这个实例包装成ObjectFactory添加到三级缓存中,这样有其他引用就可以暂时获取这个未创建完成的bean
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

        // 设置属性等初始化过程

		return exposedObject;
	}

用个简单的流程图来大致说明一下:

Spring循环依赖

public class A {
    public A(B b) {
    }
}

public class B {
    public B(A a) {
    }
}

Spring的Bean创建流程我们也知道,构造函数上的循环依赖是没有办法处理的,实例化都执行不了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值