Spring中BeanDefinitionRegistryPostProcessor接口 -【Spring底層原理】

blogg57

1、概述

上一篇咱們講到spring中BeanFactoryPostProcessor能夠對bean進行修改拓展,Spring中BeanFactoryPostProcessor接口 -【Spring底層原理】,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的一個子接口,那BeanDefinitionRegistryPostProcessor是否是能夠對BeanDefinitionRegistry進行修改拓展呢,答案是確定的,那什麼是BeanDefinitionRegistry呢,瞭解BeanDefinitionRegistry,首先得要知道什麼是BeanDefinitionjava

【1】BeanDefinitionspring

容器中的每個bean都會有一個對應的BeanDefinition實例,該實例負責保存bean對象的全部必要信息,包括bean對象的class類型、是不是抽象類、構造方法和參數、其它屬性等等。數組

【2】BeanDefinitionRegistrymarkdown

BeanDefinition是定義bean的,BeanDefinitionRegistry則是bean定義信息的保存中心,也叫註冊中心,保存了bean的全部定義,之後BeanFactory就是按照BeanDefinitionRegistry裏面保存的每個bean定義信息建立bean實例。bean是單例仍是多例,bean的類型,bean的ID等信息,都是存在BeanDefinitionRegistry裏面。app

綜上,BeanDefinitionRegistryPostProcessor就是bean定義註冊中心的後置處理器,容許咱們修改拓展bean定義信息的註冊中心,在全部bean定義信息將要被加載,bean實例還未建立的時候執行oop

2、實例分析

// 啓動測試類
@Test
public void TestMain(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    String[] beanNames = applicationContext.getBeanDefinitionNames();
    for (String beanName : beanNames) {
        System.out.println(beanName);
    }
}

// 待注入的bean
public class User {
}

// BeanDefinitionRegistryPostProcessor實現類
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry");
        System.out.println("bean的數量:"+ beanDefinitionRegistry.getBeanDefinitionCount());
        // 經過bean的構建器生成rootbean
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("hello",beanDefinition);

    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory");
        System.out.println("bean的數量:" + configurableListableBeanFactory.getBeanDefinitionCount());
    }
}

// 配置類
@Configuration
@ComponentScan("postprocessor")
public class AppConfig {
}
複製代碼

能夠看到輸出結果以下,從中咱們能夠看出:源碼分析

  • 先執行postProcessBeanDefinitionRegistry方法,獲取到IOC容器中bean的數量爲7
  • 而後給Registry裏面註冊一個hello
  • 再執行postProcessBeanFactory方法,因爲上面又註冊了一個,因此這裏獲取到IOC容器中bean的數量爲8
  • 等BeanDefinitionRegistryPostProcessor裏面的方法都執行完後,再執行BeanFactoryPostProcessor裏面的方法

image-20210319140530528

3、源碼分析

一樣,咱們經過Debug的方式來分析源碼,在postProcessBeanDefinitionRegistry方法處打個斷點,啓動斷點調試,根據方法調用棧來進行跟蹤:post

image-20210319154228551

經過查看方法調用棧,能夠做出以下分析:測試

  • 啓動IOC容器調用refresh方法
  • 再依次調用invokeBeanFactoryPostProcessors()——>invokeBeanDefinitionRegistryPostProcessors()方法
  • 在invokeBeanDefinitionRegistryPostProcessors方法中獲取到currentRegistryProcessors參數
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    ......
    // 獲取到BeanDefinitionRegistryPostProcessor組件
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    var16 = postProcessorNames;
    var9 = postProcessorNames.length;

    for(var10 = 0; var10 < var9; ++var10) {
        ppName = var16[var10];
        if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 獲取currentRegistryProcessors參數
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
        }
    }
    
    ......
        while(reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            String[] var19 = postProcessorNames;
            var10 = postProcessorNames.length;

            for(int var26 = 0; var26 < var10; ++var26) {
                String ppName = var19[var26];
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }

            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 1.在這個方法裏面觸發postProcessBeanDefinnitionRegistry
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
        }
    // 2.在這個方法裏面觸發postProcessBeanFactory方法
    invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
    invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
	......
    // 3.在這個方法裏面觸發postProcessorBeanFactory方法
    invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
    ......
}
複製代碼

從源碼能夠看到:ui

  • 先獲取BeanDefinitionRegistryPostProcessor組件
  • 再按照必定規則(如優先級)加入到currentRegistryProcessors數組中
  • currentRegistryProcessors做爲參數傳給invokeBeanDefinitionRegistryPostProcessors方法,最後在這個方法執行
  • 下圖能夠看到此時已經將本身寫的MyBeanDefinitionRegistryPostProcessor組件給獲取到了

image-20210319155522363

【1】觸發BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry

進入invokeBeanDefinitionRegistryPostProcessors方法,能夠看到,在這裏獲取到組件並觸發了postProcessBeanDefinitionRegistry:

private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
    Iterator var3 = postProcessors.iterator();

    while(var3.hasNext()) {
        BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var3.next();
        StartupStep var10000 = applicationStartup.start("spring.context.beandef-registry.post-process");
        postProcessor.getClass();
        StartupStep postProcessBeanDefRegistry = var10000.tag("postProcessor", postProcessor::toString);
        // 觸發postProcessBeanDefinnitionRegistry
        postProcessor.postProcessBeanDefinitionRegistry(registry);
        postProcessBeanDefRegistry.end();
    }
}
複製代碼

【2】觸發BeanDefinitionRegistryPostProcessor組件的BeanFactoryPostProcessor#postProcessBeanFactory

在invokeBeanDefinitionRegistryPostProcessors方法執行完後,經過invokeBeanFactoryPostProcessors方法執行postProcessBeanFactory,點進源碼進行查看:

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    Iterator var2 = postProcessors.iterator();

    while(var2.hasNext()) {
        BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
        StartupStep var10000 = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process");
        postProcessor.getClass();
        StartupStep postProcessBeanFactory = var10000.tag("postProcessor", postProcessor::toString);
        // 執行postProcessBeanFactory
        postProcessor.postProcessBeanFactory(beanFactory);
        postProcessBeanFactory.end();
    }
}
複製代碼

【3】觸發其餘組件的BeanFactoryPostProcessor#postProcessBeanFactory

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    Iterator var2 = postProcessors.iterator();

    while(var2.hasNext()) {
        BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
        StartupStep var10000 = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process");
        postProcessor.getClass();
        StartupStep postProcessBeanFactory = var10000.tag("postProcessor", postProcessor::toString);
        // 觸發postProcessorBeanFactory方法
        postProcessor.postProcessBeanFactory(beanFactory);
        postProcessBeanFactory.end();
    }

}
複製代碼

經過源碼能夠看到的執行順序:

  1. 執行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
  2. 執行BeanDefinitionRegistryPostProcessor組件的BeanFactoryPostProcessor#postProcessBeanFactory
  3. 執行其餘組件的BeanFactoryPostProcessor#postProcessBeanFactory

4、總結

  1. AnnotationConfigApplicationContext:建立IOC對象

  2. refresh()——>invokeBeanFactoryPostProcessors():執行BeanDefinitionRegistryPostProcessor

  3. 從容器中獲取到全部的BeanDefinitionRegistryPostProcessor組件

    1. 依次觸發全部的postProcessBeanDefinitionRegistry()方法

    2. 再來觸發postProcessorBeanFactory()方法BeanFactoryPostProcessor

  4. 再來從容器中找到BeanFactoryPostProcessor組件,而後依次觸發postProcessorBeanFactory()方法

從這個總結也能夠看出postProcessBeanDefinitionRegistry()方法要先於BeanFactoryPostProcessor()執行

相關文章
相關標籤/搜索