BeanFactoryPostProcessor 是 Spring 框架中重大的扩展点,它允许开发者在 Spring 容器实例化任何 bean 之前,对 bean 的定义(即 BeanDefinition)进行修改。它是 Spring IoC 容器生命周期中的关键一环,常用于实现配置属性的外部化、动态修改 bean 定义、注册额外的 bean 等高级功能。
✅作者前面的文章有讲过Spring最重大的扩展点 BeanPostProcessor,可以私信参考。
一、基本概念
1.1 定义
BeanFactoryPostProcessor 是一个接口,定义如下:
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 方法 postProcessBeanFactory() 接收一个 ConfigurableListableBeanFactory 实例。
- 此方法在所有 bean 定义被加载之后、bean 实例化之前执行。
- 开发者可以在这个阶段读取或修改 bean 的元数据(如类名、作用域、属性值、依赖关系等),但不能操作 bean 实例本身(由于尚未创建)。
⚠️ 注意:此时容器中的 bean 尚未被实例化,因此不能通过 getBean() 获取 bean 实例(除非是 FactoryBean 或特殊处理),否则可能破坏容器的初始化流程。
二、执行时机
Spring 容器启动过程中,BeanFactoryPostProcessor 的执行顺序大致如下:
- 加载并解析配置元数据(XML、注解、Java Config 等) → 得到 BeanDefinition 集合。
- 调用所有注册的 BeanFactoryPostProcessor。
- 先执行实现了 PriorityOrdered 的;
- 再执行实现了 Ordered 的;
- 最后执行普通的。
- 实例化所有非懒加载的单例 bean。
因此,BeanFactoryPostProcessor 是在 bean 实例化前、定义加载后介入的“中间层”。
执行流程图

三、常见实现类
3.1 PropertySourcesPlaceholderConfigurer
- 替换 bean 定义中的占位符(如 ${jdbc.url})为实际值。
- 从 Environment 中的 PropertySource 获取属性值。
- 是 @Value(“${…}”) 和 XML 中 <context:property-placeholder /> 的底层实现。
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
注意:必须声明为 static,由于 BeanFactoryPostProcessor 需要在普通 bean 创建前生效。
3.2 ConfigurationClassPostProcessor
- 处理带有 @Configuration、@ComponentScan、@Import、@Bean 等注解的类。
- 是基于 Java Config 的核心处理器。
- 自动注册,无需手动配置。
3.3 自定义 BeanFactoryPostProcessor
示例:动态修改某个 bean 的属性值
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("userService");
if (bd != null) {
// 修改属性值
bd.getPropertyValues().addPropertyValue("timeout", 5000);
// 或修改作用域
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
}
注册方式:
- XML:<bean/>
- Java Config:使用 @Bean(且一般为 static)
- 组件扫描 + @Component(不推荐,因可能被当作普通 bean 处理)
四、与 BeanPostProcessor的区别
|
特性 |
BeanFactoryPostProcessor |
BeanPostProcessor |
|
作用对象 |
BeanDefinition (元数据) |
bean 实例 |
|
执行时机 |
bean 实例化之前 |
bean 实例化之后、初始化前后 |
|
可否修改 bean 定义 |
✅ 可以 |
❌ 不可以 |
|
可否访问其他 bean |
❌ 不提议(可能未创建) |
✅ 可以(但注意循环依赖) |
|
典型用途 |
属性替换、动态注册 bean、修改作用域等 |
AOP 代理、初始化前后增强等 |
五、高级用法
5.1 动态注册 BeanDefinition
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
RootBeanDefinition bd = new RootBeanDefinition(MyService.class);
bd.setScope(BeanDefinition.SCOPE_SINGLETON);
registry.registerBeanDefinition("dynamicService", bd);
}
注意:需将 beanFactory 强转为 BeanDefinitionRegistry(DefaultListableBeanFactory 实现了该接口)。
5.2 条件化处理
结合 Environment 判断是否启用某功能:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
Environment env = beanFactory.getBean(Environment.class);
if ("dev".equals(env.getProperty("app.profile"))) {
// 开发环境特殊处理
}
}
5.3 优先级控制
实现 PriorityOrdered 或 Ordered 接口控制执行顺序:
public class HighPriorityBPP implements BeanFactoryPostProcessor, PriorityOrdered {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 优先执行
}
}
六、注意事项
- 避免在 postProcessBeanFactory 中调用 getBean()
除非你明确知道该 bean 是 FactoryBean 或已准备好,否则会导致提前初始化,破坏依赖注入顺序,甚至引发循环依赖问题。 - 静态工厂方法注册
在 Java Config 中,@Bean 方法应声明为 static,确保在 ApplicationContext 初始化早期就能创建该处理器。@Configuration
public class AppConfig {
@Bean
public static MyBeanFactoryPostProcessor myBPP() {
return new MyBeanFactoryPostProcessor();
}
} - 线程安全
BeanFactoryPostProcessor 一般只在容器启动时执行一次,无需思考线程安全,但若持有状态需谨慎。 - 不要修改已实例化的 bean
此阶段所有 bean 都未实例化,只能操作 BeanDefinition。
七、推荐源码阅读
在 AbstractApplicationContext.refresh() 方法中:
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
内部会:
- 找出所有 BeanFactoryPostProcessor 类型的 bean;
- 按 PriorityOrdered → Ordered → 普通排序;
- 依次调用 postProcessBeanFactory()。
八、典型应用场景
- 配置中心集成(如 Apollo、Nacos):动态替换占位符。
- 多租户系统:根据租户 ID 动态修改数据源 bean。
- 安全审计:自动为某些 service 注入审计逻辑(通过修改 bean 定义)。
- 环境差异化部署:开发/测试/生产环境动态调整 bean 行为。
总结
BeanFactoryPostProcessor 是 Spring 提供的底层、强劲的扩展机制,允许在 bean 实例化前干预其定义。合理使用它可以实现高度灵活的配置和动态行为,但需谨慎操作,避免破坏容器的正常生命周期。
掌握BeanFactoryPostProcessor对深入理解 Spring 技术栈超级重大。













暂无评论内容