Bean生命周期各阶段的解析参考:
本文介绍贯穿Spring Bean生命周期的所有后置处理器,它们在Bean的生命周期中发挥着不可缺少的作用,同时也是IOC容器的重要扩展点,通过实现这些后置处理器,开发者可以实现自己的Bean创建逻辑
分类
BeanPostProcessor:在bean对象的初始化阶段前后添加自定义的处理逻辑BeanFactoryPostProcessor:在IOC容器的生命周期中,所有BeanDefinition都是在注册到BeanDefinitionRegistry之后切入回调,此处理器的主要工作是访问/修改已经存在的BeanDefinitionBeanDefinitionRegistryPostProcessor:它是针对BeanDefinitionRegistry的后置处理器,它的执行时机比BeanFactoryPostProcessor早,这意味着BeanDefinitionRegistryPostProcessor可以在BeanFactoryPostProcessor之前注册新的BeanDefinition。
作用
BeanPostProcessor与BeanFactoryPostProcessor主要针对IOC容器中的bean,在其生命周期中进行一些切入处理和干预。- 而
BeanDefinitionRegistryPostProcessor则可以在BeanFactoryPostProcessor处理BeanDefinition之前向BeanFactory中注册新的BeanDefinition。它们的区别是:BeanFactoryPostProcessor主要是访问和修改BeanDefinition,而BeanDefinitionRegistryPostProcessor则是添加新的BeanDefinition。
BeanPostProcessor与BeanFactoryPostProcessor都有一些扩展的子接口,它们切入的时机也不尽相同。但总结性的一点就是:IOC容器的可扩展性非常强,扩展手段中很大一部分就是借助后置处理器。
BeanPostProcessor
源码
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;
}
}
方法作用
postProcessBeforeInitialization:
在Bean初始化方法(如InitializingBean的afterPropertiesSet方法、自定义init-method)执行之前,对Bean进行后处理。这个方法允许修改Bean实例的属性,或者返回一个包装后的Bean。注意:此时Bean的属性注入(依赖注入)已经完成。
典型应用:
- 在
InitDestroyAnnotationBeanPostProcessor实现类重写的postProcessBeforeInitialization方法中,会执行Bean中标记了@PostConstruct注解的初始化方法
postProcessAfterInitialization:
在Bean初始化方法执行之后,对Bean进行后处理。这个方法同样可以对Bean进行修改或包装,通常用于代理对象的创建(如AOP代理)或者添加一些额外的处理逻辑。
执行时机
这两个方法在Bean生命周期的初始化阶段执行,具体流程如下:
- 实例化:通过构造函数或工厂方法创建Bean的实例。
- 属性注入:为Bean设置属性(依赖注入)。
- 初始化:
- 完成实例化与依赖注入后,进入初始化阶段,会按顺序执行如下方法:
- 执行
BeanPostProcessor.postProcessBeforeInitialization方法:即@PostConstruct注解标记的初始化方法会执行 - 若实现了
InitializingBean接口,调用afterPropertiesSet方法。 - 如果有自定义的初始化方法则进行调用,即通过
@Bean(initMethod)或XML中的init-method指定的方法 - 最后执行
BeanPostProcessor.postProcessAfterInitialization方法:在初始化方法之后执行。
- 执行
- 完成实例化与依赖注入后,进入初始化阶段,会按顺序执行如下方法:
- 使用:此时Bean已经可以使用,存在于应用上下文中,可以被其他Bean依赖或通过上下文获取。
执行顺序
BeanPostProcessor的执行顺序:对于多个BeanPostProcessor的实现,可以通过实现Ordered接口或使用@Order注解来指定它们的执行顺序。顺序影响postProcessBeforeInitialization和postProcessAfterInitialization方法的执行顺序。postProcessBeforeInitialization:按Ordered接口指定的优先级顺序执行(数值越小优先级越高)。postProcessAfterInitialization:按Ordered接口指定的优先级顺序的逆序执行(数值越小越先执行,但在后置处理器中,实际上也是按顺序执行,但通常我们希望代理类的后置处理器最后执行,以便能够代理到所有之前处理过的Bean)。
应用场景
-
postProcessBeforeInitialization:适用于需要在初始化前对Bean进行处理的场景,例如:
- 对Bean的属性进行验证。
- 记录Bean的状态。
- 修改Bean的属性(尽管在属性注入后修改可能会覆盖依赖注入的值,需谨慎)。
-
postProcessAfterInitialization:适用于初始化后对Bean进行处理的场景,例如:
- 创建代理对象(如AOP代理,Spring的AOP就是通过这种方式实现的)。
- 对Bean进行装饰(添加额外的功能)。
- 对Bean进行记录或注册。
使用示例
下面是一个简单的例子,展示如何使用BeanPostProcessor:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization: " + beanName);
return bean; // 可以返回原Bean,或者经过修改的Bean,甚至是代理对象
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization: " + beanName);
return bean;
}
@Override
public int getOrder() {
return 0; // 指定执行顺序
}
}
重要实现
BeanPostProcessor的扩展,该后置处理器有几个重要的派生接口
-
InstantiationAwareBeanPostProcessor -
MergedBeanDefinitionPostProcessor -
SmartInstantiationAwareBeanPostProcessor -
DestructionAwareBeanPostProcessor
下面进行逐一介绍:
1.InstantiationAwareBeanPostProcessor
它会干预bean对象的实例化阶段,
InstantiationAwareBeanPostProcessor会拦截并替换bean对象的默认实例化动作,也会拦截bean对象的属性注入和自动装配,并以此控制流程。
它在BeanPostProcessor的基础上扩展了3个方法,它们分别干预bean对象的实例化动作前后以及切入属性赋值的动作:
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
postProcessBeforeInstantiation方法
作用:
- 在目标bean实例化之前执行(即调用构造方法创建实例之前)。
- 该方法可以返回一个代理对象来替代原bean的实例。如果返回非null对象,则Spring容器将使用该对象作为bean,并且不会继续执行默认的实例化流程(也就是不会再调用构造方法创建实例)。
- 如果此方法返回了非null对象,
postProcessAfterInitialization也会在后续被执行 - 如果返回null,则Spring会继续执行默认的实例化行为(即通过构造方法创建实例)。
执行时机:
- 在bean的实例化阶段的最开始。具体来说,在调用
doCreateBean方法创建bean时,会先尝试使用postProcessBeforeInstantiation方法来创建对象。如果成功则跳过默认的实例化和属性注入等步骤。
典型应用:
- 在Spring AOP中,
AbstractAutoProxyCreator就实现了这个方法,用于在bean实例化之前创建代理。但是注意,默认情况下它返回null,因为通常是在初始化后阶段创建代理。然而,对于某些特殊的bean(如TargetSource),可能会在实例化前就创建代理。
postProcessAfterInstantiation方法
作用:
- 控制是否继续属性注入:该方法返回一个布尔值。如果返回true,则Spring会继续进行后续的属性填充(如自动装配等);如果返回false,则跳过spring默认的属性注入处理(即不会进行任何属性设置,包括自动装配注解等)。
- 注意:此方法不能返回代理对象,它只是决定是否进行属性填充。
执行时机:
- 在bean实例化完成(已经通过构造方法创建了对象)之后,属性注入执行前调用该方法(如果有对应实现)。其具体在属性注入阶段中的执行时机如下,加粗部分:
- 先执行
MergedBeanDefinitionPostProcessor处理器的postProcessMergedBeanDefinition方法,收集Bean的初始化、销毁及依赖注入相关的元数据信息 - 然后调用
SmartInstantiationAwareBeanPostProcessor后置处理器的getEarlyBeanReference方法获取早期Bean用于处理循环依赖 - 执行
InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation方法(如果有该方法的实现),来处理自定义依赖注入逻辑,如果此方法返回false则跳过后面的步骤,即跳过spring默认的属性注入处理 - 最后如果上面没有返回
false,执行InstantiationAwareBeanPostProcessor处理器的postProcessProperties方法进行依赖注入,这一步就是对@Autowired进行处理。
- 先执行
典型应用:
- 用于在属性填充前进行一些自定义操作,比如检查bean的状态,或者设置一些标志。如果返回false,则可以阻止Spring进行自动装配。例如,可以检查如果某个bean的属性已经通过其他方式(比如从缓存中)设置好了,那么就不需要再进行属性注入了。
postProcessProperties方法
用于执行属性注入,它允许开发者在属性注入阶段介入,实现自定义的依赖注入逻辑。
postProcessProperties方法有个重要的实现为AutowiredAnnotationBeanPostProcessor,它是Spring 最核心的处理器之一,负责 @Autowired 和 @Value 注入。
该方法的主要作用包括:
- 修改属性值:在属性被设置到Bean之前,对属性值进行修改或替换。
- 添加或删除属性:可以添加新的属性值或删除已有的属性值。
- 自定义依赖注入逻辑:实现更复杂的依赖注入逻辑,例如根据条件决定是否注入某些属性。
- 处理注解驱动的注入:Spring内置的
@Autowired和@Value注解的处理就是通过该方法的实现类AutowiredAnnotationBeanPostProcessor完成的。
执行时机:
-
在 Bean 实例化之后、属性注入阶段中 执行,更精确地说,它是在属性注入阶段中被调用,可在属性被应用到Bean之前对其进行修改,来影响注入结果
-
紧随
postProcessAfterInstantiation之后(如后者返回 true) -
在
AbstractAutowireCapableBeanFactory.populateBean()方法中,调用顺序清晰展示了其位置:protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { // 1.实例化后立即检查: postProcessAfterInstantiation if (!continueWithPropertyPopulation) { return; // 如果返回false, 则跳过整个属性填充 } // 2.收集属性值(从注解、XML等) PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 3.调用postProcessProperties(核心环节) if (this.instantiationAwareBeanPostProcessors != null) { for (InstantiationAwareBeanPostProcessor bp : this.instantiationAwareBeanPostProcessors) { // 在此处执行postProcessProperties PropertyValues processedPvs = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (processedPvs == null) { return; } pvs = processedPvs; // 使用修改后的属性值 } } // 4.应用属性值到Bean applyPropertyValues(beanName, mbd, bw, pvs); }
2.MergedBeanDefinitionPostProcessor
核心作用 :收集Bean的初始化、销毁及自动注入相关的元数据信息用于生命周期中使用
MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition个方法,用于收集Bean的初始化、销毁及自动注入相关的元数据信息。只有提前收集好相关信息,IOC容器才会把Bean的依赖注入、初始化及销毁处理好。
方法源码
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
方法参数解析:
| 参数 | 类型 | 描述 |
|---|---|---|
beanDefinition | RootBeanDefinition | 合并后的最终 Bean 定义 |
beanType | Class<?> | Bean 的 Class 对象 |
beanName | String | Bean 在容器中的名称 |
Spring Framework中有一个非常重要的MergedBeanDefinitionPostProcessor实现,他就是AutowiredAnnotationBeanPostProcessor,它负责给bean对象实现基于注解的自动注入(如@Autowired、@Resource、@Inject等)。
MergedBeanDefinitionPostProcessor的重要实现
| 实现类 | 功能 | 关键操作 |
|---|---|---|
AutowiredAnnotationBeanPostProcessor | 处理自动注入 | 缓存 @Autowired 字段/方法,用于依赖注入 |
InitDestroyAnnotationBeanPostProcessor | 处理初始化与销毁 | 缓存 @PostConstruct、@PreDestroy方法,用于执行初始化与销毁 |
CommonAnnotationBeanPostProcessor | 处理 JSR-250 注解 | 缓存@Resource字段/方法,用于依赖注入 |
3.SmartInstantiationAwareBeanPostProcessor
提供了两个方法:
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException {
return null;
}
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
determineCandidateConstructors方法
主要作用: 在Bean实例化时,确定实例化Bean要使用的构造函数。
执行时机:
-
在创建Bean实例前执行。在开始创建Bean执行
doCreateBean方法后,会调用到createBeanInstance进行Bean实例的创建,createBeanInstance方法中会调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法来确定构造器,确定之后就会使用构造器来创建出Bean实例。// 当满足如下任一条件时,通过构造方法进行Bean的实例化 // 1. 通过SmartInstantiationAwareBeanPostProcessor后置处理器找到了构造器 // 2. 配置了注入方式是AUTOWIRE_CONSTRUCTOR,即构造器注入 // 3. 定义bean的时候指定了constructor-arg,它是用于注入构造函数参数的标签,在xml的<bean>标签中指定 // 4. 构造bean时传入了args参数 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //使用构造方法实例化bean return autowireConstructor(beanName, mbd, ctors, args); }
getEarlyBeanReference方法
作用: 解决循环依赖,在 Bean 未完成初始化前提供可用的引用
注意: 这个方法只会在出现循环依赖的情况下被调用,用于提前返回一个Bean的引用(可能是原始对象,也可能是代理对象)。如果没有循环依赖,则不会调用此方法。
关键触发点:
- 在三级缓存处理时调用:当 Spring 检测到循环依赖时
- 在 Bean 初始化之前:此时 Bean 还未完成属性填充和初始化
- 只针对单例 Bean:原型(prototype)作用域的 Bean 不支持循环依赖
执行时机,在第4步:
- 实例化BeanA(调用构造函数)
- 将BeanA并放入三级缓存(此时还不会调用
getEarlyBeanReference) - 执行
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition,收集注入信息 - 开始BeanA的属性填充,在填充属性时,发现需要注入BeanB,于是去创建BeanB。在创建BeanB的过程中,发现BeanB也需要注入BeanA,此时就会从三级缓存中获取BeanA,进而调用
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference,然后返回这个BeanA的早期引用给BeanB。
因此,在发生循环依赖时,getEarlyBeanReference的调用是发生在MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法之后,马上进行依赖注入之前
4.DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor切入的时机是bean对象的销毁阶段。当IOC容器关闭时,会销毁容器中所有的单实例bean,该处理器会在ApplicationContext的close方法调用时执行。
postProcessBeforeDestruction方法
核心作用:执行Bean的销毁逻辑,可自定义,如资源清理、回调触发等。
典型应用: 在InitDestroyAnnotationBeanPostProcessor实现的postProcessBeforeDestruction方法中,会执行@PreDestroy注解标注的Bean销毁方法
执行时机
容器关闭触发销毁,或手动销毁bean时,详细步骤:
- 当Spring容器关闭或者调用
ConfigurableApplicationContext.close()时,容器开始销毁所有单例bean。 - 对于每个单例bean,销毁过程按照以下顺序:
- 先调用所有
DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,@PreDestroy注解标记的销毁方法会在这里执行(如果Bean中有该注解标记的方法) - 接着调用
DisposableBean接口的destroy()方法(如果bean实现了这个接口)。 - 最后调用 @Bean 中指定的
destroy-method方法。
- 先调用所有
注意事项
原型作用域bean:
- 对于原型bean,Spring容器不会自动销毁,因此该方法不会被自动调用。
- 如果确实需要销毁原型bean,需要手动调用
destroy()方法,并确保配置了合适的后处理器。
BeanFactoryPostProcessor
BeanFactoryPostProcessor操作的是Bean的配置元信息,即BeanDefinition。BeanFactoryPostProcessor可以在bean对象创建之前修改Bean的定义信息,由于spring中所有的bean对象在没有实例化前都是以BeanDefinition形式存在的,如果提前修改了BeanDefinition,那么Bean在实例化时,最终创建的bean对象就会受影响。
代码
BeanFactoryPostProcessor中只定义了一个方法,就是对BeanFactory的后置处理:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
在BeanFactoryPostProcessor触发时,所有的BeanDefinition都已经被加载,但此时还没有实例化任何bean对象,在这个阶段中BeanFactoryPostProcessor可以给Bean覆盖或添加属性,甚至可以用于创建Bean对象(不推荐)。
BeanDefinitionRegistryPostProcessor
作用
BeanDefinitionRegistryPostProcessor的执行时机比BeanFactoryPostProcessor要早,它可以在 BeanFactoryPostProcessor之前注册新的BeanDefinition,作用是向BeanFactory中注册BeanDefinition,也就是增加BeanDefinition。
如果说BeanFactoryPostProcessor是修改BeanDefinition的,那么BeanDefinitionRegistryPostProcessor则是在BeanFactoryPostProcessor触发之前增加BeanDefinition的,甚至可以注册新的BeanFactoryPostProcessor用于下一阶段的回调。
典型应用:BeanDefinitionRegistryPostProcessor有一个实现类 ConfigurationClassPostProcessor ,Spring就是它来实现注解配置类的解析,并将解析结果构建为BeanDefinition注册到容器中的。配置类的解析是Bean生命周期开始的第一步,后续所有步骤都是基于BeanDefinition实现的。
代码
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
执行时机
容器启动后执行刷新方法,在刷新方法内会开始执行BeanDefinitionRegistryPostProcessor后置处理器,具体可参见生命周期的Bean定义章节。
补充: 如果需要在BeanFactory的后置处理阶段动态注册新的BeanDefinition,还可以使用ImportBeanDefinitionRegistrar
正常流程下的执行顺序与时机
容器启动执行刷新
BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry- 时机:在应用启动 --> IOC容器刷新时
- 作用:向BeanFactory中注册新的BeanDefinition
- 典型应用:Spring通过此处理器实现注解配置类的解析
- 补充:还可以使用ImportBeanDefinitionRegistrar注册新的BeanDefinition
BeanFactoryPostProcessor.postProcessBeanFactory- 时机:在bean对象实例化之前,BeanDefinitionRegistryPostProcessor之后
- 作用:在bean对象初始化之前增删改BeanDefinition中的属性、或移除BeanDefinition
- 注意:无法增加BeanDefinition,因为其触发时,所有的BeanDefinition都已经被加载。
实例化前
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation- 时机:在目标bean实例化之前执行(即调用构造方法创建实例之前)
- 作用:可返回代理对象替代原始 Bean
- 特殊行为:若返回非 null,即返回代理bean后,则跳过后续实例化和初始化流程
SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors- 时机:执行
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation之后,调用构造方法创建实例之前 - 作用:确定使用哪个构造函数进行Bean实例化
- 时机:执行
实例化后
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition- 时机:实例化后,依赖注入之前
- 作用:处理合并后的 BeanDefinition,收集Bean的初始化、销毁及依赖注入相关信息
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference- 时机:实例化后,依赖注入之前
- 作用:将早期Bean的引用存入缓存来解决循环依赖问题
- 特点:只针对单例 Bean,原型(prototype)作用域的 Bean 不支持循环依赖
- 注意:如果没有发生循环依赖,此接口方法不触发。
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation- 时机:实例化后,依赖注入之前
- 作用:进行自定义的依赖注入,如果此方法返回false则跳过spring默认的属性注入处理
- 典型应用:自定义属性填充控制逻辑
依赖注入过程中
InstantiationAwareBeanPostProcessor.postProcessProperties:- 时机:依赖注入过程中,此方法会执行注解依赖注入
- 作用:处理
@Autowired、@Inject、@Resource注解依赖注入
依赖注入后,初始化前
BeanPostProcessor.postProcessBeforeInitialization:- 时机:初始化方法执行之前
- 作用:初始化前对Bean进行处理
- 典型应用:执行
@PostConstruct注解标注的Bean的初始化方法
初始化后
BeanPostProcessor.postProcessAfterInitialization- 时机:初始化方法完成后
- 作用:做初始化后置处理,主要是创建代理对象,并将实现了
ApplicationListener接口的bean注册为事件监听器等 - 典型应用:
AbstractAutoProxyCreator创建最终代理(即返回最终包装对象 AOP 代理)
销毁
DestructionAwareBeanPostProcessor.postProcessBeforeDestruction- 时机:容器关闭或手动调用销毁逻辑
- 作用:执行Bean的销毁
- 典型应用:执行标记了
@PreDestroy注解的销毁方法
整体流程图
完整流程如下

405

被折叠的 条评论
为什么被折叠?



