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

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.dtcms.com/a/326231.html

相关文章:

  • 进程的理解
  • 无人机航拍数据集|第12期 无人机停车场车辆计数目标检测YOLO数据集1568张yolov11/yolov8/yolov5可训练
  • 数字图像处理4
  • Spring Framework源码解析——InitializingBean
  • 线程池ThreadPoolExecutor源码剖笔记
  • 对自己的 app 进行分析, 诊断,审视
  • pcl完成halcon3d中的下采样(按对角个数)
  • 网络资源模板--基于Android Studio 实现的手绘板App
  • DNS(域名系统)详解与 BIND 服务搭建
  • C# 异步编程(BeginInvoke和EndInvoke)
  • 【Java后端】Quartz任务调度核心机制详解:从基础编排到动态控制
  • Qwen 3 架构深度解析:混合推理、MoE创新与开源生态的全面突破
  • CSPOJ:1561: 【提高】买木头
  • 智能小e-智能办公文档
  • OCAD for Orienteering 20Crack 定向越野:工作流程
  • Chrome插件开发【Service Worker练手小项目】
  • MySQL 运算符
  • [CSP-J 2021] 小熊的果篮
  • Oracle数据库Library cache lock阻塞问题排查
  • 银河麒麟V10配置KVM的Ubuntu虚机GPU直通实战
  • AI测试平台实战:深入解析自动化评分和多模型对比评测
  • 人工智能-python-机器学习-逻辑回归与K-Means算法:理论与应用
  • 机器学习之DBSCAN
  • Redis中的AOF原理详解
  • 【unity实战】在Unity中实现不规则模型的网格建造系统(附项目源码)
  • CI/CD的持续集成和持续交付
  • 变频器实习DAY26 CDN 测试中心使用方法
  • 标准IO详解(fgets、gets、fread、fwrite、fseek 等应用)
  • ubuntu24.04设置登陆背景图片
  • 【openEuler构建测试环境或部署嵌入式系统】openEuler生态扩容新路径:内网穿透工具cpolar助力多场景落地