spring 的后置处理器是 spring 生态得以繁荣的一个重要基础, 大量流行的框架都使用了各种类型的 PostProcessor 增强了自身的能力, 并为开发者提供了无数便利;
BeanDefinition 的后置处理
两种 BeanFactory 处理器对比
BeanDefinitionRegistryPostProcessor
和 BeanFactoryPostProcessor
是 Spring 框架中用于在容器启动过程中对 Bean 定义进行扩展和修改的两个重要接口, 它们的主要区别在于作用时机和功能范围;
BeanFactoryPostProcessor
BeanFactoryPostProcessor 是 Spring 提供的一个接口,允许在 Spring 容器实例化 Bean 之前对 BeanDefinition 进行修改; 它主要用于在容器加载 Bean 定义之后、实例化 Bean 之前,对 Bean 定义进行全局的修改或扩展;
使用场景:
- 修改 Bean 定义:例如,修改 Bean 的属性值、添加新的属性、修改 Bean 的作用域等。
- 动态注册 Bean:虽然 BeanFactoryPostProcessor 本身不能直接注册新的 Bean,但可以通过获取 BeanFactory 来间接实现。
- 配置文件的处理:例如,解析自定义的配置文件并将其转换为 Spring 的 Bean 定义。
举例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 Bean 定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口,它在 BeanFactoryPostProcessor 的基础上提供了更早的扩展点。它允许在 Spring 容器加载 Bean 定义的过程中,直接操作 BeanDefinitionRegistry,从而可以动态注册、修改或删除 Bean 定义;
使用场景:
- 动态注册 Bean:在容器启动时,根据某些条件动态注册新的 Bean 定义。
- 修改或删除 Bean 定义:在 Bean 定义加载到容器之前,对已有的 Bean 定义进行修改或删除。
- 与 BeanFactoryPostProcessor 结合使用:在 BeanFactoryPostProcessor 之前执行,确保在 Bean 定义加载的早期阶段进行干预。
举例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 动态注册一个新的 Bean 定义
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBean.class);
registry.registerBeanDefinition("myDynamicBean", beanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 可以在这里对 BeanFactory 进行进一步的处理
}
}
对比总结
特性 | BeanFactoryPostProcessor | BeanDefinitionRegistryPostProcessor |
---|---|---|
作用时机 | 在 Bean 定义加载之后、Bean 实例化之前 | 在 Bean 定义加载过程中,比 BeanFactoryPostProcessor 更早 |
功能范围 | 只能修改已有的 Bean 定义 | 可以动态注册、修改或删除 Bean 定义 |
继承关系 | 是 BeanDefinitionRegistryPostProcessor 的父接口 | 是 BeanFactoryPostProcessor 的子接口 |
使用场景 | 修改 Bean 定义、处理配置文件 | 动态注册 Bean、修改或删除 Bean 定义 |
使用建议:
- 如果你只需要修改已有的 Bean 定义,使用
BeanFactoryPostProcessor
即可。 - 如果你需要在 Bean 定义加载的过程中动态注册新的 Bean 或对 Bean 定义进行更早的干预,使用
BeanDefinitionRegistryPostProcessor
。
通过合理使用这两个接口,可以在 Spring 容器启动过程中对 Bean 定义进行灵活的扩展和定制;
加载与执行时机
PostProcessorRegistrationDelegate1
2
3
4AbstractApplicationContext:
refresh() -> invokeBeanFactoryPostProcessors(beanFactory)
PostProcessorRegistrationDelegate:
invokeBeanFactoryPostProcessors(beanFactory, beanFactoryPostProcessors)
先处理参数传进来的 beanFactoryPostProcessors:1
foreach processor in beanFactoryPostProcessors:
然后处理已注册到 beanDefinitionRegistry 的 custom beanFactoryPostProcessors:1
2
3
4
5
6// 从 registry 找出所有已注册的 beanFactoryPostProcessor 的 beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 优先处理
BeanFactoryPostProcessor:
postProcessBeanFactory(beanFactory)