Spring Framework源码解析——BeanPostProcessor


版权声明


一、概述

BeanFactoryPostProcessor 是 Spring IoC 容器中用于在容器实例化任何 Bean 之前,对 BeanFactory 本身进行定制化修改 的核心扩展接口。它允许开发者在 Spring 容器启动过程中,修改已注册的 BeanDefinition 元数据,例如更改属性值、添加依赖、注册新的 Bean、修改作用域等。

BeanPostProcessor(作用于 Bean 实例)不同,BeanFactoryPostProcessor 作用于 BeanDefinition 阶段,是 Spring 容器可扩展性的重要体现之一。


二、接口定义

java 复制代码
public interface BeanFactoryPostProcessor {

    /**
     * 在所有 BeanDefinition 加载完成后,但在任何 Bean 被实例化前调用
     * @param beanFactory 当前使用的 BeanFactory(通常是 ConfigurableListableBeanFactory)
     * @throws BeansException 如果处理失败
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

核心特征如下:

  • 执行时机早 :在 refresh() 流程中,早于 Bean 实例化;
  • 操作对象是 BeanFactoryBeanDefinition,而非 Bean 实例;
  • 可以修改、注册、删除 BeanDefinition
  • 通常用于配置处理、占位符替换、条件注册等场景

三、注册与执行机制

注册方式如下:

BeanFactoryPostProcessor 可通过以下方式注册:

  1. 作为普通 Bean 被 Spring 扫描并注册 (如使用 @Component);
  2. 通过 ApplicationContext.addBeanFactoryPostProcessor() 手动添加
  3. Spring 内部自动注册 (如 ConfigurationClassPostProcessorPropertySourcesPlaceholderConfigurer)。

注意:BeanFactoryPostProcessor 必须是单例,否则不会被识别。


四、核心执行流程:invokeBeanFactoryPostProcessors

该方法是 BeanFactoryPostProcessor 执行的核心逻辑,定义在 AbstractApplicationContext 中。

java 复制代码
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

实际执行委托给 PostProcessorRegistrationDelegate

java 复制代码
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    Set<String> processedBeans = new HashSet<>();

    // 1. 处理实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (postProcessor instanceof PriorityOrdered) {
            priorityOrderedPostProcessors.add(postProcessor);
        }
    }
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 2. 处理实现了 Ordered 接口的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (!processedBeans.contains(postProcessor) && postProcessor instanceof Ordered) {
            orderedPostProcessors.add(postProcessor);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 3. 处理其余的 BeanFactoryPostProcessor(无排序)
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (!processedBeans.contains(postProcessor) && !(postProcessor instanceof PriorityOrdered || postProcessor instanceof Ordered)) {
            nonOrderedPostProcessors.add(postProcessor);
        }
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 4. 从 BeanFactory 中获取 BeanFactoryPostProcessor 类型的 Bean 并执行
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    List<BeanFactoryPostProcessor> registryProcessors = new ArrayList<>();
    List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

    for (String ppName : postProcessorNames) {
        if (!processedBeans.contains(ppName)) {
            BeanFactoryPostProcessor pp = beanFactory.getBean(ppName, BeanFactoryPostProcessor.class);
            if (pp instanceof BeanDefinitionRegistryPostProcessor) {
                registryProcessors.add(pp);
            } else {
                regularPostProcessors.add(pp);
            }
        }
    }

    // 4.1 先执行 BeanDefinitionRegistryPostProcessor(特殊子接口)
    invokeBeanDefinitionRegistryPostProcessors(registryProcessors, registry);

    // 4.2 再执行普通的 BeanFactoryPostProcessor
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

五、BeanDefinitionRegistryPostProcessor:更早的扩展点

BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的子接口,提供了更早的介入时机。

java 复制代码
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * 在标准的 postProcessBeanFactory 之前调用
     * 允许注册新的 BeanDefinition
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

执行顺序如下:

  1. postProcessBeanDefinitionRegistry():允许注册新的 BeanDefinition;
  2. postProcessBeanFactory():允许修改已存在的 BeanDefinition。

典型应用ConfigurationClassPostProcessor 就是 BeanDefinitionRegistryPostProcessor 的实现,负责解析 @Configuration 类,扫描 @Component,处理 @Import 等。


六、核心方法详解

invokeBeanFactoryPostProcessors(List<...>, BeanFactory)如下:

java 复制代码
private static void invokeBeanFactoryPostProcessors(
        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}
  • 遍历所有 BeanFactoryPostProcessor
  • 按顺序调用 postProcessBeanFactory 方法
  • 每个处理器都可以修改 beanFactory 中的 BeanDefinition

七、Spring 内置常用 BeanFactoryPostProcessor 实现

类名 功能
ConfigurationClassPostProcessor 解析 @Configuration@ComponentScan@Import@Bean 等注解,注册 BeanDefinition
PropertySourcesPlaceholderConfigurer 替换 ${...} 占位符(如数据库配置)
CustomAutowireConfigurer 配置自定义的自动装配策略
LoadTimeWeaverConfigurer 配置加载时织入(LTW)
MapperScannerConfigurer(MyBatis-Spring) 扫描 MyBatis Mapper 接口并注册为 Bean

八、自定义 BeanFactoryPostProcessor 示例

8.1 修改 Bean 属性

java 复制代码
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 获取某个 Bean 的定义
        BeanDefinition bd = beanFactory.getBeanDefinition("myService");
        
        // 修改其属性
        MutablePropertyValues pv = bd.getPropertyValues();
        pv.add("timeout", 5000); // 设置超时时间
        
        // 修改作用域
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
    }
}

8.2 动态注册新 Bean

java 复制代码
@Component
public class DynamicBeanRegistrationPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 动态注册一个新 Bean
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyDynamicBean.class);
        builder.addPropertyValue("name", "dynamicBean");
        registry.registerBeanDefinition("dynamicBean", builder.getBeanDefinition());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 可选:进一步修改 BeanFactory
    }
}

九、与 BeanPostProcessor 的对比

对比项 BeanFactoryPostProcessor BeanPostProcessor
作用对象 BeanFactory / BeanDefinition Bean 实例
执行时机 所有 BeanDefinition 加载后,Bean 实例化前 Bean 实例化后,初始化前后
主要用途 修改 Bean 元数据、注册新 Bean、配置替换 增强 Bean 行为、创建代理、属性注入
典型应用 @Configuration 解析、${} 替换 @Autowired、AOP 代理
执行顺序 更早 较晚

十、执行顺序控制

BeanFactoryPostProcessor 的执行顺序遵循以下优先级:

  1. PriorityOrdered 实现:最高优先级;
  2. Ordered 实现:次高优先级;
  3. 无排序接口的处理器:最后执行;
  4. 通过 ApplicationContext.addBeanFactoryPostProcessor() 添加的处理器优先于容器中注册的 Bean

可通过实现 Ordered 接口或使用 @Order 注解控制顺序。


BeanFactoryPostProcessor 是 Spring 容器生命周期中最早可扩展的切入点之一,它允许开发者在 Bean 实例化之前对容器的元数据进行修改。理解其源码执行流程与设计思想,有助于深入掌握 Spring 的配置驱动、自动装配、条件注册等高级特性。

BeanFactoryPostProcessor核心要点小结:

  • BeanFactoryPostProcessor 作用于 BeanDefinition 阶段;
  • 执行时机早于 Bean 实例化;
  • 支持修改、注册、删除 BeanDefinition
  • BeanDefinitionRegistryPostProcessor 提供更早的注册能力;
  • Spring 内部多个核心功能(如 @Configuration@ComponentScan)依赖此机制;
  • 自定义实现可用于动态配置、条件注册、属性增强等场景。

相关推荐
dylan_QAQ9 小时前
【附录】Spring AOP 基础知识及应用
后端·spring
dylan_QAQ10 小时前
【附录】Spring 配置属性绑定 基础及应用
后端·spring
dylan_QAQ10 小时前
【附录】Spring 缓存支持 基础及应用
后端·spring
笑衬人心。11 小时前
缓存的三大问题分析与解决
java·spring·缓存
duration~11 小时前
SpringAI实现Reread(Advisor)
java·人工智能·spring boot·spring
YuforiaCode11 小时前
24SpringCloud黑马商城微服务整合Seata重启服务报错的解决办法
java·spring·微服务
蓝眸少年CY12 小时前
(第三篇)spring cloud之Zookeeper注册中心
spring·spring cloud·zookeeper
dylan_QAQ13 小时前
【附录】Spring 环境配置 基础及应用
后端·spring
碎花里13 小时前
IOC控制反转深度解析
spring