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接口,可以实现以下功能:

  1. 修改Bean定义:可以在BeanFactory加载Bean定义后,对Bean定义进行修改。例如,可以根据某些条件动态修改Bean的属性值、更改Bean的作用域等。
  2. 注册新的Bean定义:可以在BeanFactory加载Bean定义后,向BeanFactory中注册新的Bean定义。这样,可以动态地向Spring容器中添加新的Bean定义,从而实现动态扩展。
  3. 添加自定义元数据:可以向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接口实现所需的功能,并确保应用程序的正常运行和可维护性。

 

posted @ 2023-12-07 13:41  残城碎梦  阅读(826)  评论(0编辑  收藏  举报