Spring的BeanFactoryPostProcessor接口详解
BeanFactoryPostProcessor作用
BeanFactoryPostProcessor是Spring框架中的一个重要接口,用于在BeanFactory加载Bean定义之后、实例化Bean之前对BeanFactory进行自定义修改和扩展。它允许开发人员在Spring容器加载配置文件并创建Bean实例之前对Bean定义进行操作,例如修改属性值、添加额外的元数据等。
BeanFactoryPostProcessor接口定义了一个方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
这个方法接收的参数是ConfigurableListableBeanFactory类型,这是Spring容器的核心接口,也是BeanFactory接口的子接口。ConfigurableListableBeanFactory可以通过继承自BeanFactory的方法获取容器中所有的Bean,并支持像BeanPostProcessor这样的接口,从而增强bean的扩展能力。
ConfigurableListableBeanFactory在Spring框架中唯一实现类是:DefaultListableBeanFactory。
在应用程序启动时,Spring容器会自动检测并调用所有实现了BeanFactoryPostProcessor接口的类的postProcessBeanFactory方法。开发人员可以利用这个方法来实现自定义的逻辑,对BeanFactory进行修改和扩展。
通过实现BeanFactoryPostProcessor接口,可以实现以下功能:
- 修改Bean定义:可以在BeanFactory加载Bean定义后,对Bean定义进行修改。例如,可以根据某些条件动态修改Bean的属性值、更改Bean的作用域等。
- 注册新的Bean定义:可以在BeanFactory加载Bean定义后,向BeanFactory中注册新的Bean定义。这样,可以动态地向Spring容器中添加新的Bean定义,从而实现动态扩展。
- 添加自定义元数据:可以向Bean定义中添加自定义的元数据,以供后续的处理器使用。这样,其他处理器或组件可以根据这些元数据进行相应的处理。
需要注意的是,BeanFactoryPostProcessor的实现类必须在Spring容器启动之前被注册到容器中,以确保在容器加载Bean定义时能够被正确调用。
总结起来,BeanFactoryPostProcessor是Spring框架中用于对BeanFactory进行自定义修改和扩展的接口。通过实现该接口,可以在BeanFactory加载Bean定义后、实例化Bean之前对BeanFactory进行修改,从而实现一些高级的自定义逻辑和功能扩展。
BeanFactoryPostProcessor的重要实现
BeanDefinitionRegistryPostProcessor接口
BeanFactoryPostProcessor的一个非常重要的子接口。
PropertySourcesPlaceholderConfigurer
用properties文件的配置值替换xml文件中的占位符。
BeanFactory后置处理器之PropertySourcesPlaceholderConfigurer
CustomEditorConfigurer
实现类型转换
BeanFactoryPostProcessor执行时机
- AbstractApplicationContext#refresh
/**
* 【步骤1:刷新前准备工作】
**/
prepareRefresh();
/**
* 【步骤2:获取刷新的BeanFactory】
**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 【步骤3:进一步完善 BeanFactory,为它的各项成员变量赋值】
*
**/
prepareBeanFactory(beanFactory);
/**
* 【步骤4:空实现,留给子类扩展】
**/
postProcessBeanFactory(beanFactory);
/**
* 【步骤5:调用 beanFactory 后处理器】
* 实例化所有的BeanDefinitionRegistryPostProcessor,并调用其postProcessBeanDefinitionRegistry方法
* 实例化所有的BeanFactoryPostProcessor,并调用其postProcessBeanFactory方法
*
* beanFactory 后处理器,充当 beanFactory 的扩展点,可以用来补充或修改 BeanDefinition
* 常见的beanFactory后处理器有:
* - ConfigurationClassPostProcessor:解析 @Configuration、@Bean、@Import、@PropertySource 等
* - PropertySourcesPlaceHolderConfigurer:替换 BeanDefinition 中的 ${ }
* 此处ConfigurationClassPostProcessor依次会解析处理这些注解
* - @PropertySource
* - @ComponentScan、@ComponentScans
* - @Import
* - @ImportResource
* - @Bean注解的方法
**/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 【步骤6:实例化bean后处理器】
**/
registerBeanPostProcessors(beanFactory);
/**
* 【步骤7:为 ApplicationContext 添加 messageSource 成员,实现国际化功能】
**/
initMessageSource();
/**
* 【步骤8:为ApplicationContext 添加事件广播器成员,即 applicationContextEventMulticaster】
**/
initApplicationEventMulticaster();
/**
* 【步骤9:空实现,留给子类扩展】
**/
onRefresh();
/**
* 【步骤10:从多种途径找到事件监听器,并添加至 applicationEventMulticaster】
**/
registerListeners();
/**
* 【步骤11:将beanFactory的成员补充完毕,并初始化所有非延迟单例 bean】
**/
finishBeanFactoryInitialization(beanFactory);
/**
* 【步骤12:为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean】
**/
finishRefresh();
- AbstractApplicationContext#invokeBeanFactoryPostProcessors
- PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
(1)处理BeanDefinitionRegistryPostProcessor接口,实例化并调用postProcessBeanDefinitionRegistry方法
执行顺序:PriorityOrdered >> Ordered >> 其他
重要:ConfigurationClassPostProcessor是Spring框架中唯一实现BeanDefinitionRegistryPostProcessor接口的实现类,它会扫描相关的配置类,将对应的Bean Definition注册到BeanFactory中。
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 收集所有BeanDefinitionRegistryPostProcessor的Bean名称
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//判断是不是PriorityOrdered得实现类,优先执行
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//调用beanFactory的getBean方法进行实例化
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//触发调用每个BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
(2)处理BeanFactoryPostProcessor接口,并实例化,调用postProcessBeanFactory方法
执行顺序:PriorityOrdered >> Ordered >> 其他
//收集所有BeanFactoryPostProcessor实现类的bean名称
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 优先执行实现PriorityOrdered接口的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 其次执行实现Ordered接口的
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后才是其他的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
BeanFactoryPostProcessor的扩展举例
注册新的Bean定义
该扩展的使用本意是指:当需要在BeanFactory加载Bean定义后,向BeanFactory中注册新的Bean定义时,可以使用BeanFactoryPostProcessor接口来实现。
假设我们有一个名为AdditionalBean的Bean类:
public class AdditionalBean {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void displayMessage() {
System.out.println("Additional Bean");
}
}
现在,我们希望在Spring容器加载Bean定义后,自动向容器中注册一个名为additionalBean的AdditionalBean实例。首先,创建一个实现了BeanFactoryPostProcessor接口的自定义类MyBeanFactoryPostProcessorForNewDefinitionReg:
@Component
public class MyBeanFactoryPostProcessorForNewDefinitionReg implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(AdditionalBean.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("additionalBean", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// 这里留空
}
}
MyBeanFactoryPostProcessorForNewDefinitionReg实现了BeanDefinitionRegistryPostProcessor接口,并重写了postProcessBeanDefinitionRegistry方法。在该方法中,我们使用BeanDefinitionBuilder构建了一个AdditionalBean的BeanDefinition实例,并使用registry.registerBeanDefinition方法将其注册到BeanDefinitionRegistry中,其中第一个参数是Bean的名称,第二个参数是BeanDefinition实例。
修改Bean定义
该扩展的使用本意是指:当需要在Spring容器加载Bean定义后对Bean的定义进行修改时,可以使用BeanFactoryPostProcessor接口来实现。
@Component
public class MyBeanFactoryPostProcessorForUpdateBean implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("myTestMsgBean");
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.add("message", "Hello, World!");
}
}
添加自定义元数据
当需要向Bean定义中添加自定义的元数据,以供后续处理器使用时,可以使用BeanFactoryPostProcessor接口来实现。
假设我们有一个名为AdditionalBean的Bean类,如之前的代码,现在,我们希望在Bean定义中添加一个自定义的元数据,例如customData,以供其他处理器或组件使用。
@Component
public class MyBeanFactoryPostProcessorForDefineMata implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition("additionalBean");
beanDefinition.setAttribute("customData", "This is custom data");
//获取的的时候使用BeanDefinition对应的getAttribute()方法获取
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// 这里留空
}
}
使用时的建议及注意事项
当使用BeanFactoryPostProcessor接口来实现自定义功能时,以下是一些使用注意事项和建议:
1)BeanFactoryPostProcessor在BeanFactory加载Bean定义后执行,但在Bean实例化之前执行。这意味着,BeanFactoryPostProcessor可以修改Bean定义的属性,但无法修改Bean实例的状态。如果需要在Bean实例化后修改Bean的属性或执行其他操作,可以考虑使用BeanPostProcessor接口。
2)避免在BeanFactoryPostProcessor中创建循环依赖关系。BeanFactoryPostProcessor的执行顺序是在Bean实例化之前,因此如果在BeanFactoryPostProcessor中创建新的Bean实例,且该实例依赖于其他Bean,可能会导致循环依赖的问题。
3)尽量避免在BeanFactoryPostProcessor中引入复杂的业务逻辑。BeanFactoryPostProcessor的主要目的是对BeanFactory进行修改和扩展,而不是执行复杂的业务逻辑。如果需要执行复杂的业务逻辑,可以考虑使用其他适合的组件,如BeanPostProcessor或自定义的Service类。
4)注意BeanFactoryPostProcessor的执行顺序。如果有多个BeanFactoryPostProcessor实现类,它们的执行顺序可能对结果产生影响。可以使用@Order注解或实现Ordered接口来指定执行顺序,或者使用Ordered接口的优先级常量(如Ordered.HIGHEST_PRECEDENCE)。
5)谨慎使用BeanFactoryPostProcessor注册新的Bean定义。注册新的Bean定义可能会导致应用程序的复杂性增加,因此应谨慎使用。确保新注册的Bean定义符合应用程序的需求,并避免过度依赖动态注册的Bean。
6)在使用BeanFactoryPostProcessor时,建议遵循单一职责原则。每个BeanFactoryPostProcessor类应该专注于一个特定的任务或功能,以保持代码的清晰性和可维护性。
7)注意BeanFactoryPostProcessor的生命周期。BeanFactoryPostProcessor实现类是在应用程序上下文的启动阶段执行的,因此需要确保它们的执行时间较短,以避免影响应用程序的启动性能。通过遵循这些注意事项和建议,可以更好地使用BeanFactoryPostProcessor接口实现所需的功能,并确保应用程序的正常运行和可维护性。