Bean生命周期中的后置处理器

Bean生命周期各阶段的解析参考:

本文介绍贯穿Spring Bean生命周期的所有后置处理器,它们在Bean的生命周期中发挥着不可缺少的作用,同时也是IOC容器的重要扩展点,通过实现这些后置处理器,开发者可以实现自己的Bean创建逻辑

分类

  • BeanPostProcessor:在bean对象的初始化阶段前后添加自定义的处理逻辑
  • BeanFactoryPostProcessor:在IOC容器的生命周期中,所有BeanDefinition都是在注册到BeanDefinitionRegistry之后切入回调,此处理器的主要工作是访问/修改已经存在的BeanDefinition
  • BeanDefinitionRegistryPostProcessor:它是针对BeanDefinitionRegistry的后置处理器,它的执行时机比BeanFactoryPostProcessor早,这意味着BeanDefinitionRegistryPostProcessor可以在BeanFactoryPostProcessor之前注册新的BeanDefinition

作用

  1. BeanPostProcessorBeanFactoryPostProcessor主要针对IOC容器中的bean,在其生命周期中进行一些切入处理和干预。
  2. BeanDefinitionRegistryPostProcessor则可以在BeanFactoryPostProcessor处理BeanDefinition之前向BeanFactory中注册新的BeanDefinition。它们的区别是:BeanFactoryPostProcessor主要是访问和修改BeanDefinition,而BeanDefinitionRegistryPostProcessor则是添加新的BeanDefinition

BeanPostProcessorBeanFactoryPostProcessor都有一些扩展的子接口,它们切入的时机也不尽相同。但总结性的一点就是: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初始化方法(如InitializingBeanafterPropertiesSet方法、自定义init-method执行之前对Bean进行后处理。这个方法允许修改Bean实例的属性,或者返回一个包装后的Bean。注意:此时Bean的属性注入(依赖注入)已经完成。

典型应用:

  • InitDestroyAnnotationBeanPostProcessor实现类重写的postProcessBeforeInitialization方法中,会执行Bean中标记了 @PostConstruct 注解的初始化方法

postProcessAfterInitialization:

在Bean初始化方法执行之后,对Bean进行后处理。这个方法同样可以对Bean进行修改或包装,通常用于代理对象的创建(如AOP代理)或者添加一些额外的处理逻辑。


执行时机

这两个方法在Bean生命周期的初始化阶段执行,具体流程如下:

  1. 实例化:通过构造函数或工厂方法创建Bean的实例。
  2. 属性注入:为Bean设置属性(依赖注入)。
  3. 初始化
    • 完成实例化与依赖注入后,进入初始化阶段,会按顺序执行如下方法:
      • 执行BeanPostProcessor.postProcessBeforeInitialization方法:即@PostConstruct 注解标记的初始化方法会执行
      • 若实现了InitializingBean接口,调用afterPropertiesSet方法。
      • 如果有自定义的初始化方法则进行调用,即通过@Bean(initMethod)或XML中的init-method指定的方法
      • 最后执行BeanPostProcessor.postProcessAfterInitialization方法:在初始化方法之后执行。
  4. 使用:此时Bean已经可以使用,存在于应用上下文中,可以被其他Bean依赖或通过上下文获取。

执行顺序

  • BeanPostProcessor的执行顺序:对于多个BeanPostProcessor的实现,可以通过实现Ordered接口或使用@Order注解来指定它们的执行顺序。顺序影响postProcessBeforeInitializationpostProcessAfterInitialization方法的执行顺序。
  • 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 注入。

该方法的主要作用包括:

  1. 修改属性值:在属性被设置到Bean之前,对属性值进行修改或替换。
  2. 添加或删除属性:可以添加新的属性值或删除已有的属性值。
  3. 自定义依赖注入逻辑:实现更复杂的依赖注入逻辑,例如根据条件决定是否注入某些属性。
  4. 处理注解驱动的注入: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);

方法参数解析:

参数类型描述
beanDefinitionRootBeanDefinition合并后的最终 Bean 定义
beanTypeClass<?>Bean 的 Class 对象
beanNameStringBean 在容器中的名称

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方法中会调用SmartInstantiationAwareBeanPostProcessordetermineCandidateConstructors 方法来确定构造器,确定之后就会使用构造器来创建出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步:

  1. 实例化BeanA(调用构造函数)
  2. 将BeanA并放入三级缓存(此时还不会调用getEarlyBeanReference
  3. 执行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition,收集注入信息
  4. 开始BeanA的属性填充,在填充属性时,发现需要注入BeanB,于是去创建BeanB。在创建BeanB的过程中,发现BeanB也需要注入BeanA,此时就会从三级缓存中获取BeanA,进而调用SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference,然后返回这个BeanA的早期引用给BeanB。

因此,在发生循环依赖时,getEarlyBeanReference的调用是发生在MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition方法之后,马上进行依赖注入之前


4.DestructionAwareBeanPostProcessor

DestructionAwareBeanPostProcessor切入的时机是bean对象的销毁阶段。当IOC容器关闭时,会销毁容器中所有的单实例bean,该处理器会在ApplicationContextclose方法调用时执行。

postProcessBeforeDestruction方法

核心作用:执行Bean的销毁逻辑,可自定义,如资源清理、回调触发等。

典型应用:InitDestroyAnnotationBeanPostProcessor实现的postProcessBeforeDestruction方法中,会执行@PreDestroy注解标注的Bean销毁方法

执行时机

容器关闭触发销毁,或手动销毁bean时,详细步骤:

  1. 当Spring容器关闭或者调用ConfigurableApplicationContext.close()时,容器开始销毁所有单例bean。
  2. 对于每个单例bean,销毁过程按照以下顺序:
    • 先调用所有DestructionAwareBeanPostProcessorpostProcessBeforeDestruction方法,@PreDestroy注解标记的销毁方法会在这里执行(如果Bean中有该注解标记的方法)
    • 接着调用DisposableBean接口的destroy()方法(如果bean实现了这个接口)。
    • 最后调用 @Bean 中指定的destroy-method方法。

注意事项

原型作用域bean

  • 对于原型bean,Spring容器不会自动销毁,因此该方法不会被自动调用。
  • 如果确实需要销毁原型bean,需要手动调用destroy()方法,并确保配置了合适的后处理器。

BeanFactoryPostProcessor

BeanFactoryPostProcessor操作的是Bean的配置元信息,即BeanDefinitionBeanFactoryPostProcessor可以在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



正常流程下的执行顺序与时机

容器启动执行刷新

  1. BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
    • 时机:在应用启动 --> IOC容器刷新时
    • 作用:向BeanFactory中注册新的BeanDefinition
    • 典型应用:Spring通过此处理器实现注解配置类的解析
    • 补充:还可以使用ImportBeanDefinitionRegistrar注册新的BeanDefinition
  2. BeanFactoryPostProcessor.postProcessBeanFactory
    • 时机:在bean对象实例化之前,BeanDefinitionRegistryPostProcessor之后
    • 作用:在bean对象初始化之前增删改BeanDefinition中的属性、或移除BeanDefinition
    • 注意:无法增加BeanDefinition,因为其触发时,所有的BeanDefinition都已经被加载。

实例化前

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
    • 时机:在目标bean实例化之前执行(即调用构造方法创建实例之前)
    • 作用:可返回代理对象替代原始 Bean
    • 特殊行为:若返回非 null,即返回代理bean后,则跳过后续实例化和初始化流程
  2. SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors
    • 时机:执行InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation之后,调用构造方法创建实例之前
    • 作用:确定使用哪个构造函数进行Bean实例化

实例化后

  1. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
    • 时机:实例化后,依赖注入之前
    • 作用:处理合并后的 BeanDefinition,收集Bean的初始化销毁依赖注入相关信息
  2. SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
    • 时机:实例化后,依赖注入之前
    • 作用:将早期Bean的引用存入缓存来解决循环依赖问题
    • 特点:只针对单例 Bean,原型(prototype)作用域的 Bean 不支持循环依赖
    • 注意:如果没有发生循环依赖,此接口方法不触发。
  3. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
    • 时机:实例化后,依赖注入之前
    • 作用:进行自定义的依赖注入,如果此方法返回false则跳过spring默认的属性注入处理
    • 典型应用:自定义属性填充控制逻辑

依赖注入过程中

  1. InstantiationAwareBeanPostProcessor.postProcessProperties
    • 时机:依赖注入过程中,此方法会执行注解依赖注入
    • 作用:处理@Autowired@Inject@Resource注解依赖注入

依赖注入后,初始化前

  1. BeanPostProcessor.postProcessBeforeInitialization
    • 时机:初始化方法执行之前
    • 作用:初始化前对Bean进行处理
    • 典型应用:执行@PostConstruct注解标注的Bean的初始化方法

初始化后

  1. BeanPostProcessor.postProcessAfterInitialization
    • 时机:初始化方法完成后
    • 作用:做初始化后置处理,主要是创建代理对象,并将实现了ApplicationListener接口的bean注册为事件监听器等
    • 典型应用AbstractAutoProxyCreator 创建最终代理(即返回最终包装对象 AOP 代理)

销毁

  1. DestructionAwareBeanPostProcessor.postProcessBeforeDestruction
    • 时机:容器关闭或手动调用销毁逻辑
    • 作用:执行Bean的销毁
    • 典型应用:执行标记了@PreDestroy注解的销毁方法


整体流程图

完整流程如下

Bean后置处理器

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值