概述

  1. Spring中的每个bean的创建是依赖一个对应的`BeanDefintion`实例,该实例保存了bean对象创建必要的信息,比如beanclass类型,是否是抽象类、属性信息等。`BeanDefinitionRegistry`是一个接口,bean定义信息的注册中心,用于注册、删除、管理`BeanDefintion`。<br /> 如果外部想要添加Bean的定义信息,创建新的Bean, 怎么办? 当然是可以通过Spring提供的扩展接口`BeanDefinitionRegistryPostProcessor`实现,比较典型的一个案例是mybatis-spring,就是通过实现该接口,添加mybatis相关的bean。<br /> 所以,`**BeanDefinitionRegistryPostProcessor**`**就是bean定义注册中心的后置处理器,允许我们修改拓展bean定义信息的注册中心,在所有bean定义信息将要被加载,bean实例还未创建的时候执行。**

使用实例

  1. 新建类实现BeanDefinitionRegistryPostProcessor ```java @Component public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {

    1. log.info("******************** TestBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry ****************");
    2. log.info("******************** bean的数量:[{}] ****************", beanDefinitionRegistry.getBeanDefinitionCount());
    3. AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
    4. MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
    5. propertyValues.addPropertyValue("username", "alvin");
    6. propertyValues.addPropertyValue("age", 12);
    7. // 注册bean信息
    8. beanDefinitionRegistry.registerBeanDefinition("beanDefineDemo", beanDefinition);

    }

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

    1. log.info("******************** TestBeanDefinitionRegistryPostProcessor#postProcessBeanFactory ****************");
    2. log.info("******************** bean的数量:[{}] ****************", configurableListableBeanFactory.getBeanDefinitionCount());

    } }

  1. 2. 实现类需要添加`@Component`注解
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061737063-3893a070-bcfc-4946-a896-842188179314.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=175&id=u9e84b8fe&margin=%5Bobject%20Object%5D&name=image.png&originHeight=175&originWidth=647&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21448&status=done&style=none&taskId=ue923855d-f826-4be0-b046-8f25c8b03c1&title=&width=647)
  3. 3. 验证注入的bean
  4. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061762922-d7d668a9-56ef-4c0e-9ca5-d0a7c9cb08f8.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=242&id=ue393d30b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=242&originWidth=921&originalType=binary&ratio=1&rotation=0&showTitle=false&size=36749&status=done&style=none&taskId=ua5ad40d1-08c0-4110-a364-d381fbf302b&title=&width=921)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/384158/1654061772381-da50fa51-2890-4f9e-8e65-6485b6446c65.png#clientId=ud7accf57-2ef8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=47&id=ufcc92ed2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=47&originWidth=1207&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9943&status=done&style=none&taskId=u32a98b6e-e9cd-4e16-8c3a-2f3e6bdeb84&title=&width=1207)
  5. <a name="nqAkU"></a>
  6. # 源码解析
  7. > 可以通过debug的方式,在postProcessBeanDefinitionRegistry方法中打上断点,查看Deubbger中的Frames记录,快速定位代码的调用链路。
  8. <a name="OAsYd"></a>
  9. ## 接口的定义说明
  10. ```java
  11. /**
  12. * 扩展到标准的{@link BeanFactoryPostProcessor} SPI
  13. * 允许在常规BeanFactoryPostProcessor检测开始之前注册更多的bean定义。
  14. * 特别是,BeanDefinitionRegistryPostProcessor可以注册更多的bean定义,
  15. * 这些定义反过来又定义了BeanFactoryPostProcessor实例。
  16. *
  17. * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
  18. * the registration of further bean definitions <i>before</i> regular
  19. * BeanFactoryPostProcessor detection kicks in. In particular,
  20. * BeanDefinitionRegistryPostProcessor may register further bean definitions
  21. * which in turn define BeanFactoryPostProcessor instances.
  22. *
  23. * @author Juergen Hoeller
  24. * @since 3.0.1
  25. * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
  26. */
  27. public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
  28. /**
  29. * 在标准初始化之后修改应用程序上下文的内部bean定义注册表。所有常规bean定义都已加载,
  30. * 但还没有实例化bean。这允许在进入下一个后处理阶段之前添加更多的bean定义。
  31. *
  32. * Modify the application context's internal bean definition registry after its
  33. * standard initialization. All regular bean definitions will have been loaded,
  34. * but no beans will have been instantiated yet. This allows for adding further
  35. * bean definitions before the next post-processing phase kicks in.
  36. * @param registry the bean definition registry used by the application context
  37. * @throws org.springframework.beans.BeansException in case of errors
  38. */
  39. void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

通过翻译看,此接口目的是为了提供给开发者向容器中注册更多的BeanDefinition, 实现动态注册bean的目的。

执行流程

Spring Boot 扩展之BeanDefinitionRegistryPostProcessor接口源码解析 - 图1以上是整个执行的序列图,关键点是AbstractApplicationContext#refresh()

1. AbstractApplicationContext#refresh()

  1. public void refresh() throws BeansException, IllegalStateException {
  2. synchronized (this.startupShutdownMonitor) {
  3. StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
  4. // Prepare this context for refreshing.
  5. // 刷新上下文的准备阶段,跳过
  6. prepareRefresh();
  7. // Tell the subclass to refresh the internal bean factory.
  8. // 创建beanFacotry工厂
  9. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  10. // Prepare the bean factory for use in this context.
  11. // beanFactory准备工作, 跳过
  12. prepareBeanFactory(beanFactory);
  13. try {
  14. // Allows post-processing of the bean factory in context subclasses.
  15. postProcessBeanFactory(beanFactory);
  16. StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
  17. // Invoke factory processors registered as beans in the context.
  18. // 调用注册的BeanFactoryPostProcessors对象
  19. invokeBeanFactoryPostProcessors(beanFactory);
  20. }
  21. }

2. AbstractApplicationContext#invokeBeanFactoryPostProcessors

  1. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  2. // 注册的核心代码, beanFactory代表当前的容器, 第二个参数为内置的参数处理器
  3. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
  4. .....
  5. }

3. PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

  1. public static void invokeBeanFactoryPostProcessors(
  2. ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
  3. // WARNING: Although it may appear that the body of this method can be easily
  4. // refactored to avoid the use of multiple loops and multiple lists, the use
  5. // of multiple lists and multiple passes over the names of processors is
  6. // intentional. We must ensure that we honor the contracts for PriorityOrdered
  7. // and Ordered processors. Specifically, we must NOT cause processors to be
  8. // instantiated (via getBean() invocations) or registered in the ApplicationContext
  9. // in the wrong order.
  10. //
  11. // Before submitting a pull request (PR) to change this method, please review the
  12. // list of all declined PRs involving changes to PostProcessorRegistrationDelegate
  13. // to ensure that your proposal does not result in a breaking change:
  14. // https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
  15. // Invoke BeanDefinitionRegistryPostProcessors first, if any.
  16. // 如果存在BeanDefinitionRegistryPostProcessors,那么就会首先调用。
  17. Set<String> processedBeans = new HashSet<>();
  18. if (beanFactory instanceof BeanDefinitionRegistry) {
  19. BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
  20. // 常规的BeanFactory后置处理器集合
  21. List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
  22. // Bean定义注册的后置处理器
  23. List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
  24. // 遍历容器优先内置的后置处理器
  25. for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
  26. // 判断是否为Bean定义注册的后置处理器
  27. if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
  28. BeanDefinitionRegistryPostProcessor registryProcessor =
  29. (BeanDefinitionRegistryPostProcessor) postProcessor;
  30. // 直接调用postProcessBeanDefinitionRegistry方法
  31. registryProcessor.postProcessBeanDefinitionRegistry(registry);
  32. registryProcessors.add(registryProcessor);
  33. }
  34. else {
  35. regularPostProcessors.add(postProcessor);
  36. }
  37. }
  38. // Do not initialize FactoryBeans here: We need to leave all regular beans
  39. // uninitialized to let the bean factory post-processors apply to them!
  40. // Separate between BeanDefinitionRegistryPostProcessors that implement
  41. // PriorityOrdered, Ordered, and the rest.
  42. // 定义外部实现了BeanDefinitionRegistryPostProcessor扩展的集合
  43. List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
  44. // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
  45. // 首先,调用实现PriorityOrdered的 BeanDefinitionRegistryPostProcessor。
  46. // 此处获取的postProcessorNames必须是已经进行注册过的BeanDefinition。
  47. // 第一次我们无法找到我们写的BeanDefinitionRegistryPostProcessor,是因为它本身并未注册到bean定义注册中心。
  48. // 但是会发现有ConfigurationClassPostProcessor,它会帮我们写的PostProcessor注册到bean定义注册中心。
  49. String[] postProcessorNames =
  50. beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  51. for (String ppName : postProcessorNames) {
  52. // 判断BeanDefinitionRegistryPostProcessor是否实现了PriorityOrdered接口
  53. if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
  54. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  55. processedBeans.add(ppName);
  56. }
  57. }
  58. // 根据优先级排序
  59. sortPostProcessors(currentRegistryProcessors, beanFactory);
  60. registryProcessors.addAll(currentRegistryProcessors);
  61. // 真正执行后置处理器
  62. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
  63. currentRegistryProcessors.clear();
  64. // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
  65. // 再次获取BeanDefinitionRegistryPostProcessor后置处理器,此时可以看到我们写的后置处理器,
  66. // 那是因为我们写的后置处理器bean定义经过ConfigurationClassPostProcessor注册
  67. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  68. for (String ppName : postProcessorNames) {
  69. // 判断是否实现了Ordered接口
  70. if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
  71. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  72. processedBeans.add(ppName);
  73. }
  74. }
  75. sortPostProcessors(currentRegistryProcessors, beanFactory);
  76. registryProcessors.addAll(currentRegistryProcessors);
  77. // 真正执行后置处理器
  78. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
  79. currentRegistryProcessors.clear();
  80. // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
  81. // 最后执行没有实现Orderd接口的后置处理器
  82. boolean reiterate = true;
  83. while (reiterate) {
  84. reiterate = false;
  85. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  86. for (String ppName : postProcessorNames) {
  87. if (!processedBeans.contains(ppName)) {
  88. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  89. processedBeans.add(ppName);
  90. reiterate = true;
  91. }
  92. }
  93. sortPostProcessors(currentRegistryProcessors, beanFactory);
  94. registryProcessors.addAll(currentRegistryProcessors);
  95. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
  96. currentRegistryProcessors.clear();
  97. }
  98. // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
  99. // 因为
  100. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
  101. invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  102. }
  103. else {
  104. // Invoke factory processors registered with the context instance.
  105. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
  106. }
  107. // 后面的内容是执行BeanFactoryPostProcessor的后置处理器,后面再说
  108. .....
  109. }

小结:

  • 自己定义的后置处理器想要生效,前提是必须本身要被注册到BeanDefinitionRegistry注册中心,这也是为什么我们需要加@Component注解。
  • 那我们添加@Component注解的后置处理器在上面时候注册到BeanDefinitionRegistry注册中心呢? 实在ConfigurationClassPostProcessor中动态注册的,这也是为什么第一次获取BeanDefinitionRegistryPostProcessor相关的bean name时候,没有找到我们写的,因为我们写的还没有注册到BeanDefinitionRegistry注册中心。
  • BeanDefinitionRegistryPostProcessor的执行顺序是,实现了@PriorityOrdered优先执行,其次是实现了@Ordered,最后是没有实现的后置处理器。

    内置的BeanDefinitionRegistryPostProcessor

    SpringBoot比较重要的内置的BeanDefinitionRegistryPostProcessor后置处理器是ConfigurationClassPostProcessor,它主要是帮我们完成注解扫描和类定义注册,然后再由BeanFactory完成实例化以及初始化逻辑,那它本身是在什么时候注册到注册中心的呢,内部原理又是什么样呢?

    参考

    https://juejin.cn/post/6844903874491318280#heading-8
    https://blog.csdn.net/qq_42154259/article/details/108315262
    https://www.cnblogs.com/warrior4236/p/13157671.html
    https://cloud.tencent.com/developer/article/1928593