BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的一个子接口
    image.png
    image.png :::info BeanDefinitionRegistryPostProcessor调用时机分析 ::: BeanDefinitionRegistryPostProcessor作为BeanFactoryPostProcessor的子接口,当用户自定义BeanDefinitionRegistryPostProcessor的时候,必将同时实现两个方法,postProcessBeanDefinitionRegistry和父方法postProcessBeanFactory

    • 从IOC容器中获取到所有的BeanDefinitionRegistryPostProcessor组件
      • 并依次触发它们的postProcessBeanDefinitionRegistry方法
      • 然后再来触发它们的postProcessBeanFactory方法
    • 再来从IOC容器中获取到所有的BeanFactoryPostProcessor组件,并依次触发它们的postProcessBeanFactory方法

    今天我们重点来看BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法:
    它的参数是BeanDefinitionRegistry,顾名思义就是与BeanDefinition注册相关的。

    1. public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    2. // 注册bean到spring容器中
    3. void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    4. }

    通过观察Spring自动注入类BeanDefinitionRegistry,我们发现它里边包含了registerBeanDefinition方法,这个不就是我们想要的吗?
    组件添加BDRegistryPostProcessor接口 - 图3
    为了能更好的使用该接口来达到注入Bean的目的,我们先来看看Spring是如何操作此接口的。
    组件添加BDRegistryPostProcessor接口 - 图4
    image.png
    invokeBeanFactoryPostProcessors方法入手,优先执行BeanDefinitionRegistry类型的beanFactory
    image.png
    上述源码依次执行实现了PriorityOrderedBeanDefinitionRegistryPostProcessor和实现了OrderedBeanDefinitionRegistryPostProcessor
    进入BeanDefinitionRegistryPostProcessor接口的生效方法invokeBeanDefinitionRegistryPostProcessors,进一步发现,BeanDefinitionRegistryPostProcessor类的postProcessBeanDefinitionRegistry方法会被调用

    1. private static void invokeBeanDefinitionRegistryPostProcessors
    2. (Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry)
    3. {
    4. Iterator var2 = postProcessors.iterator();
    5. while(var2.hasNext()) {
    6. BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
    7. postProcessor.postProcessBeanDefinitionRegistry(registry);
    8. }
    9. }

    退出invokeBeanDefinitionRegistryPostProcessors方法,最后执行父接口BeanFactoryPostProcessor
    image.png :::info 代码验证 ::: 接下来编写测试代码进行验证。编写一个类MyBeanDefinitionRegistryPostProcessor,实现BeanDefinitionRegistryPostProcessor接口

    1. package com.meimeixia.ext;
    2. import org.springframework.beans.BeansException;
    3. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    4. import org.springframework.beans.factory.support.AbstractBeanDefinition;
    5. import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    6. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    7. import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
    8. import org.springframework.beans.factory.support.RootBeanDefinition;
    9. import org.springframework.stereotype.Component;
    10. import com.meimeixia.bean.Blue;
    11. // 记住,我们这个组件写完之后,一定别忘了给它加在容器中
    12. @Component
    13. public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    14. @Override
    15. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    16. // TODO Auto-generated method stub
    17. System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount());
    18. }
    19. /**
    20. * 这个BeanDefinitionRegistry就是Bean定义信息的保存中心,这个注册中心里面存储了所有的bean定义信息,
    21. * 以后,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息来创建bean实例的。
    22. *
    23. * bean定义信息包括有哪些呢?有这些,这个bean是单例的还是多例的、bean的类型是什么以及bean的id是什么。
    24. * 也就是说,这些信息都是存在BeanDefinitionRegistry里面的。
    25. */
    26. @Override
    27. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    28. // TODO Auto-generated method stub
    29. System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
    30. // 除了查看bean的数量之外,我们还可以给容器里面注册一些bean,我们以前也简单地用过
    31. /*
    32. * 第一个参数:我们将要给容器中注册的bean的名字
    33. * 第二个参数:BeanDefinition对象
    34. */
    35. // RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); // 现在我准备给容器中添加一个Blue对象
    36. // 咱们也可以用另外一种办法,即使用BeanDefinitionBuilder这个构建器生成一个BeanDefinition对象,很显然,这两种方法的效果都是一样的
    37. AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
    38. registry.registerBeanDefinition("hello", beanDefinition);
    39. }
    40. }

    接下来,我们就来测试一下以上类里面的两个方法是什么时候执行的。运行IOCTest_Ext测试类,我们可以得出这样两个结论

    • BeanDefinitionRegistryPostProcessor接口是优先于BeanFactoryPostProcessor接口执行的
    • 在BeanDefinitionRegistryPostProcessor接口中,postProcessBeanDefinitionRegistry方法优先于postProcessBeanFactory方法调用 ```shell postProcessBeanDefinitionRegistry…bean的数量: 10 MyBeanDefinitionRegistryPostProcessor…bean的数量:11

    MyBeanFactoryPostProcessor…postProcessBeanFactory… 当前BeanFactory中有9个Bean [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,…, …,org.springframework.context.event.internalEventListenerFactory,extConfig,myBeanFactoryPostProcessor,blue} blue…constructor `` 可以看到,首先postProcessBeanDefinitionRegistry方法先执行,拿到IOC容器中Bean的数量(即10)之后向IOC容器中注册一个hello组件。<br />接着是postProcessBeanFactory`方法再执行,该方法只是打印了一下IOC容器中Bean的数量11(算上hello)
    除此之外,我们自己写的MyBeanDefinitionRegistryPostProcessor类里面的方法都执行完了以后,才轮到外面那些BeanFactoryPostProcessor来执行