当前位置: 首页 > java >正文

Spring Framework源码解析——BeanPostProcessor


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

在这里插入图片描述

一、概述

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

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


二、接口定义

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 中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

实际执行委托给 PostProcessorRegistrationDelegate

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();// 1. 处理实现了 PriorityOrdered 接口的 BeanFactoryPostProcessorList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof PriorityOrdered) {priorityOrderedPostProcessors.add(postProcessor);}}sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 2. 处理实现了 Ordered 接口的 BeanFactoryPostProcessorList<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 再执行普通的 BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

五、BeanDefinitionRegistryPostProcessor:更早的扩展点

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

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)如下:

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 属性

@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic 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

@Component
public class DynamicBeanRegistrationPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 动态注册一个新 BeanBeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyDynamicBean.class);builder.addPropertyValue("name", "dynamicBean");registry.registerBeanDefinition("dynamicBean", builder.getBeanDefinition());}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 可选:进一步修改 BeanFactory}
}

九、与 BeanPostProcessor 的对比

对比项BeanFactoryPostProcessorBeanPostProcessor
作用对象BeanFactory / BeanDefinitionBean 实例
执行时机所有 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)依赖此机制;
  • 自定义实现可用于动态配置、条件注册、属性增强等场景。

http://www.xdnf.cn/news/17613.html

相关文章:

  • 【学习嵌入式day-22-Linux软件编程-IO】
  • SpringBoot集成支付宝二维码支付接口详解
  • Python3.10 + Firecrawl 下载 Markdown 文档:构建高效通用文章爬虫
  • 不同FPGA开发板系统移植步骤
  • Chrome插件开发【Service Worker练手小项目】
  • 【LeetCode刷题集】--排序(三)
  • 【智能的起源】人类如何模仿,简单的“刺激-反应”机制 智能的核心不是记忆,而是发现规律并能迁移到新场景。 最原始的智能:没有思考,只有简单条件反射
  • Mamba 原理汇总2
  • AI(2)-神经网络(激活函数)
  • 支持小语种的在线客服系统,自动翻译双方语言,适合对接跨境海外客户
  • 数据结构-数组扩容
  • 开发指南130-实体类的主键生成策略
  • Apache ECharts 6 核心技术解密 – Vue3企业级可视化实战指南
  • 排错000
  • 基于 ZooKeeper 的分布式锁实现原理是什么?
  • windows上RabbitMQ 启动时报错:发生系统错误 1067。 进程意外终止。
  • 150V降压芯片DCDC150V100V80V降压12V5V1.5A车载仪表恒压驱动H6203L惠洋科技
  • git:分支
  • 提示词工程实战:用角色扮演让AI输出更专业、更精准的内容
  • 软件测评中HTTP 安全头的配置与测试规范
  • 数据变而界面僵:Vue/React/Angular渲染失效解析与修复指南
  • 基于 Axios 的 HTTP 请求封装文件解析
  • Console Variables Editor插件使用
  • 音视频学习(五十三):音频重采样
  • QT QProcess + xcopy 实现文件拷贝
  • Web安全自动化测试实战指南:Python与Selenium在验证码处理中的应用
  • Mybatis @Param参数传递说明
  • 【工作笔记】Wrappers.lambdaQuery()用法
  • RK3588在YOLO12(seg/pose/obb)推理任务中的加速方法
  • JS数组排序算法