1、定义
BeanDefinitionRegistryPostProcessor
实际上是 BeanFactoryPostProcessor
的一个特殊化和功能更强的子接口 。
在 Spring 的 IoC 容器中,Bean 的定义(BeanDefinition) 与 Bean 的实例化 是两个阶段。而 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 正是介入这两个阶段的重要扩展点,开发者可以通过它们对 Spring 的 Bean 定义或 BeanFactory 进行定制化。
简单来说:
BeanDefinitionRegistryPostProcessor
是 "征兵官" ,负责招募新士兵(注册新的BeanDefinition)。BeanFactoryPostProcessor
是 "训练官" ,负责训练和调整已有士兵的属性(修改已注册的BeanDefinition)。
下面进行详细对比。
2、BeanDefinitionRegistryPostProcessor (BDRPP)分析
1. 身份与继承关系:
它是 BeanFactoryPostProcessor
的子接口 。这意味着一个实现了 BeanDefinitionRegistryPostProcessor
的类,同时也是一个 BeanFactoryPostProcessor
。
2. 核心方法:
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
3. 操作时机与目标:
它的执行时机早于 普通的 BeanFactoryPostProcessor
。
它操作的目标是 BeanDefinitionRegistry
。这个Registry就是Spring容器中用于注册、持有和管理所有BeanDefinition的"仓库"。
4. 主要作用与权力:
它的核心权力是动态地、编程式地向Spring容器中注册全新的BeanDefinition。这包括:
- 注册新的Bean:根据条件(如扫描特定路径、检查某个类是否存在)动态地向容器中添加新的Bean定义。
- 移除已有的Bean定义:虽然不常用,但理论上也可以从Registry中移除某个BeanDefinition。
- 当然,它也能做普通BFPP能做的事(获取和修改已存在的BeanDefinition),因为它最终也会执行
postProcessBeanFactory
方法。
5. 经典例子:
ConfigurationClassPostProcessor
:这是Spring中最重要、最核心的BDRPP。它负责解析@Configuration
类、扫描@Component
、处理@Bean
方法等。正是这个处理器,才使得我们通过注解定义的Bean能够被注册到容器中。
3、BeanFactoryPostProcessor (BFPP)分析
1. 核心方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
2. 操作时机与目标:
它的执行时机晚于 BeanDefinitionRegistryPostProcessor
。
它操作的目标是 ConfigurableListableBeanFactory
。这个BeanFactory已经包含了所有通过BDRPP注册好的BeanDefinition。
3. 主要作用与权力:
它的权力相对"小"一些,主要是对已经存在于BeanFactory中的BeanDefinition进行查询和修改 ,但不能注册全新的BeanDefinition。包括:
- 修改Bean的属性值。
- 修改Bean的作用域(Scope)。
- 处理占位符(如
${}
)。
4、执行流程与顺序
Spring容器的启动过程中,这两个处理器的执行有一个非常清晰的顺序:
- 实例化 所有
BeanFactoryPostProcessor
(包括其子类BeanDefinitionRegistryPostProcessor
)。 - 首先,调用所有
BeanDefinitionRegistryPostProcessor
的postProcessBeanDefinitionRegistry
方法。- 这些处理器向容器中注册了大量新的BeanDefinition(例如,通过注解扫描到的Bean)。
- 然后,调用所有
BeanDefinitionRegistryPostProcessor
的postProcessBeanFactory
方法(因为它们也实现了BFPP接口)。 - 最后,调用所有普通的
BeanFactoryPostProcessor
的postProcessBeanFactory
方法。- 这些处理器对现在已经完整的BeanDefinition集合进行修改和调整。
5、对比总结表
特性 | BeanDefinitionRegistryPostProcessor | BeanFactoryPostProcessor |
---|---|---|
关系 | 是BeanFactoryPostProcessor 的扩展子接口 |
父接口 |
核心方法 | postProcessBeanDefinitionRegistry |
postProcessBeanFactory |
执行顺序 | 先执行 | 后执行 (在BDRPP的postProcessBeanFactory 之后) |
操作目标 | BeanDefinitionRegistry (注册中心) |
ConfigurableListableBeanFactory (Bean工厂) |
核心权力 | 注册、移除BeanDefinition (修改容器内容) | 查询、修改已注册的BeanDefinition (调整容器内容) |
典型应用 | 编程式注册Bean、注解扫描(ConfigurationClassPostProcessor ) |
修改属性、占位符解析(PropertySourcesPlaceholderConfigurer ) |
6、代码示例
java
@Component
public class MyRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
// 第一阶段:注册新Bean
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 1. 动态注册一个全新的Bean
RootBeanDefinition beanDefinition = new RootBeanDefinition(DynamicService.class);
registry.registerBeanDefinition("dynamicService", beanDefinition);
// 2. 也可以移除已有的Bean定义
// if (registry.containsBeanDefinition("unwantedBean")) {
// registry.removeBeanDefinition("unwantedBean");
// }
}
// 第二阶段:修改已注册的Bean(和普通BFPP一样)
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("someExistingBean");
// ... 修改属性等操作
}
}
@Component
public class MyNormalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
// 只在第三阶段执行
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 此时,名为 "dynamicService" 的Bean已经被注册,这里可以获取到它并进行修改
BeanDefinition bd = beanFactory.getBeanDefinition("dynamicService");
// ... 修改操作
}
}
7、总结
你可以这样理解它们的职责划分:
BeanDefinitionRegistryPostProcessor
:负责扫描注解@Configuration、@Bean 解析然后调用 BeanDefinitionRegistry 注册 这些带有注解的 Bean的原信息。(修改容器本身)BeanFactoryPostProcessor
:负责对以及存在的BeanDefination进行修改。(修改容器内的内容)
这种设计体现了Spring框架的"开放-封闭"原则,通过不同的扩展点,允许用户在容器生命周期的不同阶段注入不同的逻辑,提供了极大的灵活性。