1. 简介
在【Spring核心流程梳理】我们介绍了Spring容器的refresh过程,但是我们并没有进入到Spring Bean的创建等生命周期等内容。
这里,就来梳理一下Spring Bean的生命周期。
我们还是关注流程,重点关注核心的入口,忽略具体实现的细节。
目标也很简单:
- 知道Spring Bean相关的扩展点,方便我们做自定义和阅读源码
- 当遇到问题的时候,能大致了解相关的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个:
- 实例化(Instantiate):创建实例,相当于new过程
- 初始化(Initialize):设置值的过程,相当于setter过程
- 销毁:一般不需要,特殊的可以做释放资源等工作
注意: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是在初始化之前执行,所以,调用顺序就能确定了:
- @PostConstuct方法
- afterPropertiesSet
- init-method
initializeBean方法中处理的Aware是:
- BeanNameAware给bean设置beanName
- BeanClassLoaderAware给bean设置ClassLoader
- BeanFactoryAware给bean设置BeanFactory
其他的Aware,通过ApplicationContextAwareProcessor,它是一个BeanPostProcessor,会在bean初始化之前,但是肯定在前面3个之后调用:
- EnvironmentAware:设置获取环境属性相关的Enviroment
- EmbeddedValueResolverAware:设置SpEL解析器
- ResourceLoaderAware:设置资源加载器
- ApplicationEventPublisherAware:设置事件发布器
- MessageSourceAware:设置国际化相关的MessageSource
- ApplicationStartupAware:设置启动指标监控相关的ApplicationStartup
- ApplicationContextAware:设置容器本身ApplicationContext
3.4 registerDisposableBeanIfNecessary方法
这个方法咱就不细入了,简单说一下逻辑:
- 处理bean中有@PreDestroy注解的方法
- 如果实现了DisposableBean接口处理其destroy方法
- 检查destroy-method,如:
4. 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;
}
用个简单的流程图来大致说明一下:
public class A {
public A(B b) {
}
}
public class B {
public B(A a) {
}
}
Spring的Bean创建流程我们也知道,构造函数上的循环依赖是没有办法处理的,实例化都执行不了。