1. 简介
本文带大家整体掌握下Spring中的Bean生命周期,让你大大提升Spring内功。学会本文,让你在解决Spring中相关问题的时候不会再出现无从下手的问题。大家一定要收藏记忆,面试也会被经经常问到。本文内容比较简单粗暴,只讲重点,建议大家后续按照文中要点看下源码,了解一下细节,顺便学习下Spring的设计思想。
2. 全局俯视生命周期 Aware、PostProcessor
这里首先介绍两个词 Aware 、PostProcessor ,Spring整个生命周期的控制都在围绕着这两个词展开,如
- BeanPostProcessor:Spring 中Bean对象的生命周期管理处理器,后面讲到的Bean每个参与环节生命周期管理的处理器都是实现了这个接口
- BeanFactoryPostProcessor:Spring 中 BeanFactory的生命周期管理器接口
- BeanNameAware 接口:当给Bean对象设置名字时会被这个接口感知到,调用接口里setBeanName()的方法
其他的这里不再列举,后面会详细介绍
3. 第一阶段: 元信息配置、解析、注册、合并阶段
3.1 第一阶段介绍
-
配置
在Spring 中通过 xml配置文件的标签 或者注解配置 @Bean、@Compontent标注的类进行配置。 -
解析
Spring 通过XmlBeanDefinitionReader
、AnnotatedBeanDefinitionReader
类把我们通过xml和注解方式配置的Bean会解析成一个BeanDefinition
对象。BeanDefinition
对象中定义了和Bean相关的信息,如Bean 的class、name、scop、parent(父类) 等待。 -
注册
DefaultListableBeanFactory
这个类 负责把定义好的BeanDefinition
注册到Spring 容器中 -
合并
在我们定义的类中有各种相互依赖继承关系,Spring会把BeanDefinition
进行合并处理,最后得到一个RootBeanDefinition
对象,后面是使用这个类进行加载,实例化等操作。
下面来段小代码理解一下
@Test
public void test() {
//使用BeanDefinitionBuilder 自定义一个 BeanDefinition 对象
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class.getName());
//设置属性
beanDefinitionBuilder.addPropertyValue("name", "法拉利");
//获取BeanDefinition
BeanDefinition carBeanDefinition = beanDefinitionBuilder.getBeanDefinition();
System.out.println(carBeanDefinition);
//创建spring容器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//调用registerBeanDefinition向容器中注册bean
factory.registerBeanDefinition("car", carBeanDefinition);
Car bean = factory.getBean("car", Car.class);
System.out.println(bean);
}
3.2. 第一阶段扩展点
3.2.1. Spring工厂扩展一:Bean 注册接阶段
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
方法会在Spring工厂注册阶段调用,注册阶段结束后Spring不会再对Bean进行注册,比如这个阶段我们可以自定义注册一些新的Bean,其他可干的事情看BeanDefinitionRegistry相关API
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
3.2.2. Spring工厂扩展二:BeanFactory后置处理
BeanFactoryPostProcessor#postProcessBeanFactory
方法会在Spring工厂注册阶段结束后调用,可以对BeanFactory进行一些扩展
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
4. 第二阶段:实例化阶段
先看代码片段
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
在所有的Bean 实例化之前都会调用此方法,去遍历BeanPostProcessor,然后执行具体的实现方法。 在Spring 中有很多类似结构的代码片段,在不同环节遍历执行不同类型的PostProcesser。所以我们要参与Bean生命周期管理,只需要实现对应类型的BeanPostProcessor接口即可,这里我按照实际执行顺序梳理一个清单出来,感兴趣可以看下源码。
4.1 实例化阶段
1.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
方法,如果此方法返回当前Bean实例,将跳过Spring自带后续的实例化过程。
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
返回一个构造器,这个构造器在new 对象时使用,如果返回null ,使用默认构造器
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException {
return null;
}
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
方法,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理。
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
它有两个实现类:
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存- org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
,对象创建完成之后调用,当这个方法返回false,后续的Bean 属性赋值都会被跳过。
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
4.2 属性赋值阶段
InstantiationAwareBeanPostProcessor#postProcessProperties
属性赋值前会调用。
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
看下调用逻辑
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
从调用逻辑可以看出,如果InstantiationAwareBeanPostProcessor
中的postProcessProperties
和postProcessPropertyValues
都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。PropertyValues
中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues
值进行修改。
两个重要实现类
- AutowiredAnnotationBeanPostProcessor在这个方法中对@Autowired、@Value标注的字段、方法注入值。
- CommonAnnotationBeanPostProcessor在这个方法中对@Resource标注的字段和方法注入值。
4.3 Bean Aware 接口回调
- 如果我们的bean实例实现了下面面的这些Aware接口, 将会按照执行顺序把 bean名称、BeanClassLoader、BeanFactory都注入进去。
private void invokeAwareMethods(final String beanName, final 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);
}
}
}
2.ApplicationContextAwareProcessor#postProcessBeforeInitialization
中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。
- EnvironmentAware:注入Environment对象
- EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
- ResourceLoaderAware:注入ResourceLoader对象
- ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
- MessageSourceAware:注入MessageSource对象
- ApplicationContextAware:注入ApplicationContext对象
4.4 初始化
CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization
中会调用bean中所有标注@PostConstruct
注解的方法- 调用
InitializingBean
接口的afterPropertiesSet
方法 - 调用定义bean的时候指定的初始化方法,如
@Bean(initMethod = "初始化的方法")
- 轮询我们自定义实现的
BeanPostProcessor#postProcessAfterInitialization
方法,当返回null的时候,会中断轮询操作。
5. 实例化完成
容器中所有非延迟加载的单例Bean初始化完成后容器会调用SmartInitializingSingleton#afterSingletonsInstantiated
方法。
本方法调用结束后,容器中的Bean就可以使用了。
6. 销毁阶段
Bean 的销毁会依次调用以下
- 轮询
轮询BeanPostProcessors
列表,调用DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
- CommonAnnotationBeanPostProcessor#postProcessBeforeDestruction 处理 @PreDestroy标注的方法
- 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
- 调用bean自定义的销毁方法,如
@Bean(destroyMethod = "销毁方法")
7.小结
- 很多生命周期环节都是在轮询
BeanPostProcessors
列表,调用其对应方法,所以想要参与Bean的生命周期,只要写一个类实现对应生命周期的BeanPostProcessors就可以 - 补充一个知识
@Order
注解 和Order
接口 可以指定在轮询BeanPostProcessors
列表时的执行顺序。