概述

BeanFactoryPostProcessor是Spring中一个相当重要的扩展点,扩展点就是能让我们在Spring容器以及Bean生命周期的各个阶段中可以进行修改扩展。

什么是BeanFactoryPostProcessor

BeanFactoryPostProcessor, 翻译过来大致是Bean的工厂处理器,顾名思义,可以理解为它对Bean工厂中Bean定义(BeanDefintion)进行修改, 它的执行时机:BeanFactory标准初始化之后,所有的Bean定义已经被加载,但标准Bean的实例还没被创建(不包括BeanFactoryPostProcessor类型)。该方法通常用于修改bean的定义,Bean的属性值等,甚至可以在此快速初始化Bean。
而另外一个相关的扩展接口的BeanDefinitionRegistryPostProcessor,继承自BeanFactoryPostProcessor,所有的Bean定义即将被加载,但Bean的实例还没被创建时,也就是说,BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法执行时机先于BeanFactoryPostProcessorpostProcessBeanFactory方法。
区别于一个很类似的扩展接口BeanPostProcessor, 它的执行时机实在Bean初始化前后,添加一些自己想要的逻辑。
小结一下,上面关联的扩展接口执行顺序如下:1.BeanDefinitionRegistryPostProcessor,2.BeanFactoryPostProcessor,3.BeanPostProcessor。而BeanFactoryPostProcessor主要是在标准的BeanDefinition已经准备完毕,可以去修改已有的BeanDefinition的相关属性等。

如何使用BeanFactoryPostProcessor

  1. 新建一个测试bean

    1. @Data
    2. @Component
    3. public class Student {
    4. @Value("${user.username:alvin}")
    5. private String username;
    6. @Value("${user.age:12}")
    7. private int age;
    8. }
  2. 新建处理器实现**BeanFactoryPostProcessor** ```java @Component @Slf4j public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    1. log.info("******************** TestBeanFactoryPostProcessor#postProcessBeanFactory ****************");
    2. log.info("******************** bean的数量:[{}] ****************", beanFactory.getBeanDefinitionCount());
    3. // 修改bean definition属性信息
    4. BeanDefinition userBeanDef = beanFactory.getBeanDefinition("student");
    5. userBeanDef.getPropertyValues().add("username", "cxw");
    6. // 快速初始化Bean
    7. User user = (User)beanFactory.getBean("student");
    8. log.info("student name: [{}]", user.getUsername());

    } }

  1. 3. **验证结论**
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654850398275-592eb0cd-4b59-4880-98d8-32e2c4de7a07.png#clientId=u6871ecff-da1d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=199&id=PkQlJ&margin=%5Bobject%20Object%5D&name=image.png&originHeight=199&originWidth=1089&originalType=binary&ratio=1&rotation=0&showTitle=false&size=50251&status=done&style=none&taskId=u0a687fa5-925a-4f50-96f8-a8312006cf4&title=&width=1089)<br />bean的属性被成功被修改了。
  3. <a name="HKEwX"></a>
  4. # 源码解析
  5. <a name="WOBrY"></a>
  6. ## 接口定义
  7. ```java
  8. /**
  9. * Factory hook that allows for custom modification of an application context's
  10. * bean definitions, adapting the bean property values of the context's underlying
  11. * bean factory.
  12. *
  13. * <p>Useful for custom config files targeted at system administrators that
  14. * override bean properties configured in the application context. See
  15. * {@link PropertyResourceConfigurer} and its concrete implementations for
  16. * out-of-the-box solutions that address such configuration needs.
  17. *
  18. * <p>A {@code BeanFactoryPostProcessor} may interact with and modify bean
  19. * definitions, but never bean instances. Doing so may cause premature bean
  20. * instantiation, violating the container and causing unintended side-effects.
  21. * If bean instance interaction is required, consider implementing
  22. * {@link BeanPostProcessor} instead.
  23. *
  24. * <h3>Registration</h3>
  25. * <p>An {@code ApplicationContext} auto-detects {@code BeanFactoryPostProcessor}
  26. * beans in its bean definitions and applies them before any other beans get created.
  27. * A {@code BeanFactoryPostProcessor} may also be registered programmatically
  28. * with a {@code ConfigurableApplicationContext}.
  29. *
  30. * <h3>Ordering</h3>
  31. * <p>{@code BeanFactoryPostProcessor} beans that are autodetected in an
  32. * {@code ApplicationContext} will be ordered according to
  33. * {@link org.springframework.core.PriorityOrdered} and
  34. * {@link org.springframework.core.Ordered} semantics. In contrast,
  35. * {@code BeanFactoryPostProcessor} beans that are registered programmatically
  36. * with a {@code ConfigurableApplicationContext} will be applied in the order of
  37. * registration; any ordering semantics expressed through implementing the
  38. * {@code PriorityOrdered} or {@code Ordered} interface will be ignored for
  39. * programmatically registered post-processors. Furthermore, the
  40. * {@link org.springframework.core.annotation.Order @Order} annotation is not
  41. * taken into account for {@code BeanFactoryPostProcessor} beans.
  42. *
  43. * @author Juergen Hoeller
  44. * @author Sam Brannen
  45. * @since 06.07.2003
  46. * @see BeanPostProcessor
  47. * @see PropertyResourceConfigurer
  48. */
  49. @FunctionalInterface
  50. public interface BeanFactoryPostProcessor {
  51. /**
  52. * Modify the application context's internal bean factory after its standard
  53. * initialization. All bean definitions will have been loaded, but no beans
  54. * will have been instantiated yet. This allows for overriding or adding
  55. * properties even to eager-initializing beans.
  56. * @param beanFactory the bean factory used by the application context
  57. * @throws org.springframework.beans.BeansException in case of errors
  58. */
  59. void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
  60. }

接口的注释很清楚的说明了它的作用和细节,大致有下面几点:

  • 该接口允许用户自定义修改工厂bean中的BeanDefinition, 调整BeanDefinition的属性值,甚至初始化Bean。比如内置的PropertyResourceConfigurer,就是修改beanDefinition的属性为配置文件的属性。
  • 该接口主要是用于修改BeanDefinition, 虽然也可以直接进行实例化Bean, 但是不建议这么做,可能会造成其他未知的错误。

    执行流程

    Spring Boot 扩展之BeanFactoryPostProcessor接口源码解析 - 图1其中核心逻辑是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法,该方法的前面部分逻辑主要是处理BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法,也就是想BeanDefinition注册中中心添加新的BeanDefinition。 ```java public static void invokeBeanFactoryPostProcessors(

    1. ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    2. .......... 该部分是处理BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry相关逻辑,跳过, 可以看BeanDefinitionRegistryPostProcessor的解析
  1. // Do not initialize FactoryBeans here: We need to leave all regular beans
  2. // uninitialized to let the bean factory post-processors apply to them!
  3. // 获取所有实现了BeanFactoryPostProcessor接口的bean name列表,前提是在BeanFactory的BeanDefinitions列表中包含对应的bean定义信息。
  4. String[] postProcessorNames =
  5. beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
  6. // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
  7. // Ordered, and the rest.
  8. // 存放实现了PriorityOrdered接口的processor
  9. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
  10. // 存放实现了Ordered接口的processor
  11. List<String> orderedPostProcessorNames = new ArrayList<>();
  12. // 存放没有实现排序的processor
  13. List<String> nonOrderedPostProcessorNames = new ArrayList<>();
  14. // 遍历前面全量的bean name,将他们归类,放到上面的容器中
  15. for (String ppName : postProcessorNames) {
  16. // 如果在第一阶段已经被调用过,就不调用,第一阶段主要是BeanDefinitionRegistryPostProcessor,它继承了BeanFactoryPostProcessor,它会在第一阶段调用。
  17. if (processedBeans.contains(ppName)) {
  18. // skip - already processed in first phase above
  19. }
  20. else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
  21. priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
  22. }
  23. else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
  24. orderedPostProcessorNames.add(ppName);
  25. }
  26. else {
  27. nonOrderedPostProcessorNames.add(ppName);
  28. }
  29. }
  30. // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
  31. // 首先执行实现了PriorityOrdered接口的processor,对它们进行排序
  32. sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
  33. // 真实执行processor中的逻辑。
  34. invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
  35. // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
  36. // 其次执行实现了Ordered接口的processor,对它们进行排序后执行processor中的逻辑。
  37. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
  38. for (String postProcessorName : orderedPostProcessorNames) {
  39. orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  40. }
  41. sortPostProcessors(orderedPostProcessors, beanFactory);
  42. invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
  43. // 最后执行,没有顺序要求的processor
  44. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
  45. for (String postProcessorName : nonOrderedPostProcessorNames) {
  46. nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  47. }
  48. invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
  49. // Clear cached merged bean definitions since the post-processors might have
  50. // modified the original metadata, e.g. replacing placeholders in values...
  51. beanFactory.clearMetadataCache();
  52. }

//调用processors中的postProcessBeanFactory方法 private static void invokeBeanFactoryPostProcessors( Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

  1. for (BeanFactoryPostProcessor postProcessor : postProcessors) {
  2. StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
  3. .tag("postProcessor", postProcessor::toString);
  4. postProcessor.postProcessBeanFactory(beanFactory);
  5. postProcessBeanFactory.end();
  6. }
  7. }

```

小结

整个执行流程的源码还是比较清晰并且简单的。重点提下下面两个点:

  1. 我们自定义的BeanFactoryProcessor需要加上**@Component**等注解,为什么?

看源码得知,String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);获取所有实现了BeanFactoryPostProcessor的Bean Name, 前提所有的Bean都要被注册到BeanDefinitionRegistry, 通过添加@Component, @Service等注解,可以将对应的Bean定义信息注册到BeanFactory中,方便后面实例化Bean。 那么它是在什么地方注册的呢?可以看下ConfigurationClassPostProcessor类,它实现了BeanDefinitionRegistryPostProcessor,会扫描所有@Component, @Service等注解,将对应的Bean Definition注册到BeanFactory中。

  1. 执行顺序问题

我们可以通过实现PriorityOrdered, Ordered接口,控制BeanFactoryProcessor的执行顺序,, 优先执行实现了PriorityOrdered接口,其次是Ordered,最后是没有实现任何排序接口的processor。

内置的BeanFactoryPostProcessor

Spring内置了一个比较重要的BeanFactoryPostProcessorPlaceholderConfigurerSupport, 实现从配置文件中获取属性。
image.png

参考

https://fangjian0423.github.io/2017/06/24/spring-embedded-bean-post-processor/