springboot筆記-2-.核心的上下文以及配置掃描解析(上)


前言

  上一節中簡要說明了下springboot自動化配置的關鍵,那么本節看下springboot真正的初始化過程,如何創建上下文並解析配置,加載我們注冊到容器管理中的類。上節已經成功的創建了SpringApplication,那我們就看下其run方法究竟做了些什么

  

正文

  我們從SpringApplication的run方法開始入手,只看核心代碼,其他省略

public ConfigurableApplicationContext run(String... args) {
        ...//省略代碼
        //聲明spring上下文
        ConfigurableApplicationContext context = null;
        try {
            ..//省略代碼
            //2.新建應用上下文
            context = createApplicationContext();
            ..//省略代碼
            //3.刷新上下文
            refreshContext(context);
            //4.完成刷新上下文后調用(目前空白)
            afterRefresh(context, applicationArguments);
            ..//省略代碼
        }
        
        return context;
    }

  通過上面我們可以發現,run方法核心步驟就是創建ApplicatonContext,這兒主要的步驟有兩個 1.創建應用上下文 2.刷新上下文。我們從創建開始看

 

1.創建spring的核心 ApplicationContext

  查看createApplicationContext方法

public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot."
            + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            switch (this.webApplicationType) {
            case SERVLET:
                //我們使用這個    
                contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
                break;
            case REACTIVE:
                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                break;
            default:
                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        }
        ..//省略
    }
    //反射生成實例
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

  這兒其實看着是很簡單的邏輯,就是根據類型,選擇與一個合適的創建,這兒我們就用常見的servlet來說明。servlet對應的上下文為AnnotationConfigServletWebServerApplicationContext。然后最后會根據反射來生成一個實例並返回。我們可以看下這個上下文的類圖

 

 

 

   相信這個類繼承結構大家都看着比較頭痛,畢竟作為核心類。這兒就挑兩個個重要的說下。

  第一。  其最終實現了BeanFactory接口,並繼承了GenericApplicationContext。並且我們查看其構造函數會傳入一個BeanFactory

    public AnnotationConfigServletWebServerApplicationContext(DefaultListableBeanFactory beanFactory) {
        super(beanFactory);
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

  最終在GenericApplicationContext中有如下代碼

private final DefaultListableBeanFactory beanFactory;

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
    Assert.notNull(beanFactory, "BeanFactory must not be null");
    this.beanFactory = beanFactory;
}

  會發現上下文不論如何都會持有一個beanFactory,很多人被問到過ApplicationContext和beanFactory的區別與聯系。其實這兒就能看出來是一個很典型的靜態代理的案例。既然是代理,就說明了肯定ApplicationContext在保持Beanfactory的原有功能時又擴展了很多功能。這樣就可以做到既兼容舊版本,又增強很多功能。當然了,具體的區別有興趣的可以去看下二者的源代碼。

  

  第二。我們在AnnotationConfigServletWebServerApplicationContext的構造函數中發現了有如下步驟 

this.reader = new AnnotatedBeanDefinitionReader(this);

  這兒新建了一個注解bean的解析器。我們一路跟着源碼看下

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

  這兒我們會發現該方法最后會為registry注冊一些解析器,我們看下AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);該方法會為Beanfactory設置一系列的BeanDefinition,以及其他的一些東西,

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);

    // 處理@Configuration @ComponentScans  @Component  @Bean等注解  @PropertySources  @ImportResource  等
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 處理 @Autowired  @Value 等
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 處理@Required @
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 處理類似@PostConstruct 和@PreDestroy
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 如果有jpa的話這里有處理的  例如@Selevt
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 處理類似@EventListener的注解
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

  可以發現這兒設置了很多BeanDefinition,尤其是是ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor這兩可以說是相當核心的兩個后置處理器,在后面spring進行配置解析的時候會相當的有用。

  

  到此,創建ApplicationContext就完成了,我們看系統刷新上下文的時候做了些什么

 

2. refreshContext  spring的核心加載方法

  該方法可以說占據了springboot啟動的絕大部分時間,也是springboot啟動中最為核心的方法。

  

    private void refreshContext(ConfigurableApplicationContext context) {
        refresh(context);
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            }
            catch (AccessControlException ex) {
                // Not allowed in some environments.
            }
        }
    }

  

    protected void refresh(ApplicationContext applicationContext) {
        Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
        ((AbstractApplicationContext) applicationContext).refresh();
    }

  跟着代碼一路走,發現其最終調用的是上下文的refresh方法。由於其被強轉為AbstractApplicationContext,所以我們直接看其refresh方法,到此就進入ApplicationContext類中了。

 

3.ApplicationContext中refresh方法

  該方法里面有很多初始化方法,我們也選擇核心的說明

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //初始化之前的一些准備,例如設置開始標記等
        prepareRefresh();

        // 獲取到上面提到的beanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 初始注冊一些要用到的類
        prepareBeanFactory(beanFactory);

        try {
            // 添加一些BeanFactory的postProcess
            postProcessBeanFactory(beanFactory);

            // 執行BeanFactory的PostProcessors
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注冊一些BeanPostProcessors
            registerBeanPostProcessors(beanFactory);

            ../略過
            
            // 一些特殊的操作,例如
            //本案例中是AnnotationConfigServletWebServerApplicationContext 那么這兒會開始創建servlet容器
            onRefresh();

            ../略過

            // 實例化容器中未設置懶加載的類
            finishBeanFactoryInitialization(beanFactory);
            
            ../略過
        }

    }
}

  這兒我們我們主要看兩個方法   一是invokeBeanFactoryPostProcessors,該方法會找出所有需要加載的bean。然后是finishBeanFactoryInitialization方法,該方法會將需要加載的bean進行實例化並裝載屬性。

 

4.invokeBeanFactoryPostProcessors方法

  該方法我們跟着源代碼走,最終會走到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,由於該方法過長。所以我們分段說明

 

4.1 無所不在的PostProcesser

  不得不說spring將切面應用到了極致啊。。基本每初始化某個東西都會有其對應的PostProcessor,雖然看着略顯繁瑣,但是卻極大的增加了我們的擴展點

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            //將我們的BeanFactory強轉為BeanDefinitionRegistry
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
            //循環我們傳入的BeanFactoryPostProcessor  如果其是BeanDefinitionRegistryPostProcessor  
            //那么這兒執行其postProcessBeanDefinitionRegistry方法
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

   上述代碼也是執行了傳入的Proccessor類型為BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。

 

4.2 第一級BeanDefinitionRegistryPostProcessor執行(即實現了PriorityOrdered接口)

 

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 找到系統所有實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor接口實現類
// 這兒會找到我們剛剛的
ConfigurationClassPostProcessor

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //排序 sortPostProcessors(currentRegistryProcessors, beanFactory); //將剛找到的BeanDefinitionRegistryPostProcessor加入registryProcessors registryProcessors.addAll(currentRegistryProcessors); //執行剛找到的BeanDefinitionRegistryPostProcessor invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); //清空 currentRegistryProcessors.clear();

  這兒即找實現了BeanDefinitionRegistryPostProcessor,PriorityOrdered的類。而我們在第一節中最后提到的ConfigurationClassPostProcessor剛好是滿足的,我們可以在回顧一下

 

 

   這兒我們進入invokeBeanDefinitionRegistryPostProcessors方法看下

    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }

  可以看到是迭代所有BeanDefinitionRegistryPostProcessor並執行其postProcessBeanDefinitionRegistry方法。而上面說到我們會拿到ConfigurationClassPostProcessor,所以這兒我們直接看ConfigurationClassPostProcessor的方法,由於該方法是spring進行配置解析的重中之重,所以篇幅較長

 

4.2.1 校驗並為本次解析設置id,防止重復加載

   第一步則是設置了本次解析的id,防止重復解析

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    //得到registry的hash碼作為id
    int registryId = System.identityHashCode(registry);
    //校驗id
    if (this.registriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
        throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);
    //正式解析
    processConfigBeanDefinitions(registry);
}

 

4.2.2 正式解析

  這兒我們依舊一段一段的看

  

List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//找到該registry所有的candidateNames  也就是我們第一步結尾添加的那些
String[] candidateNames = registry.getBeanDefinitionNames();

for (String beanName : candidateNames) {
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    //isFullConfigurationClass 判斷是否是帶有@Configuration  
    //isLiteConfigurationClass 判斷是否帶有@Component,@ComponentScan,@Import,@ImportResource,@Bean 5個注解中的任一個
    // 具體可以查看 https://blog.csdn.net/u011624903/article/details/102564491
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
            ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
    }
    // 這兒由於我們的主啟動類中@SpringbootApplication帶@Configuration注解 所以主類滿足
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
}

// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
    return;
}
// 排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
 

  這兒會將BeanFactory中已經存在的BeanDefinitionName全部查出來並獲取其BeanDefinition,由於我們的啟動類@SpringbootApplication中已經帶有@Configuration  所以這里是滿足的(第一節中講組合注解的時候講過)

  然后接下來會有查看是否有BeanNameGenerator和environment

SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }

        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }

  然后我們就看到了本文最核心的代碼了,也就是解析代碼。

  我們看下這個解析流程

// 構建一個ConfigurationClassParser   也就是解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

//拿到我們解析的配置類  這兒的話是主啟動類
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
//已經解析的ConfigurationClass集合
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
    //開始解析
    parser.parse(candidates);
    //驗證
    parser.validate();
    //找到本次解析后發現的所有ConfigurationClass
    Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    //移除掉已經解析的
    configClasses.removeAll(alreadyParsed);

    // 如果沒有  則創建一個新的ConfigurationClassBeanDefinitionReader
    if (this.reader == null) {
        this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
    }
    //將這些發現的找到本次解析后發現的所有ConfigurationClass再次解析掉
    this.reader.loadBeanDefinitions(configClasses);
    //將其添加到已解析的集合中
    alreadyParsed.addAll(configClasses);
    //清空candidates
    candidates.clear();
    //如果registry中的BeanDefinition數量大於candidateNames  也就是一開始進入方法時的數量
    //即找到的新的需要加入容器的bean了
    if (registry.getBeanDefinitionCount() > candidateNames.length) {
        //拿到所有的已經存在的BeanDefinitionName
        String[] newCandidateNames = registry.getBeanDefinitionNames();
        //初始進來的BeanDefinitionName
        Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
        //創建已經解析的Class的名字的集合
        Set<String> alreadyParsedClasses = new HashSet<>();
        for (ConfigurationClass configurationClass : alreadyParsed) {
            //將已經解析的添加到集合中
            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
        }
        //循環遍歷 所有的BeanDefinition  看看有沒有configuration被遺漏的
        for (String candidateName : newCandidateNames) {
            //即不是初始化進來時的BeanDefinition
            if (!oldCandidateNames.contains(candidateName)) {
                //拿到這個BeanDefinition
                BeanDefinition bd = registry.getBeanDefinition(candidateName);
                //如果該BeanDefinition也是一個配置類並且沒有存在於alreadyParsed  即被遺漏了
                //那么將其添加到candidates方法 然后再進行
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                    //則再將其添加進去  循環進行解析        
                    candidates.add(new BeanDefinitionHolder(bd, candidateName));
                }
            }
        }
        candidateNames = newCandidateNames;
    }
}
while (!candidates.isEmpty());

  這段代碼較長,邏輯還是較為清晰,其實通過這段代碼我們就大概明白了springboot進行配置加載的流程了。即根據主啟動類進行配置解析,並且將所有遇到的ConfigurationClass全部返回,然后再進行二次解析,最后對所有的BeanDefinition進行校驗,如果發現其為ConfigurationClass但是卻沒有在已解析的集合中,那么久循環一下,再次進行解析

  篇幅有限,具體的解析流程放到下一篇, 解析完第一級BeanDefinitionRegistryPostProcessor后我們開始解析第二級

 

  

4.3 第二級BeanDefinitionRegistryPostProcessor(即實現了Ordered接口)

  

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
          //過濾了第一級中存在的
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();

  可以發現其流程和第一級幾乎一致,只是增加了一個過濾掉了第一級,所以這兒不講,如果有自定義的BeanDefinitionRegistryPostProcessor可以測試一下。

4.4 第三級BeanDefinitionRegistryPostProcessor

  

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

  處理流程也和前兩級幾乎一致,這兒也不講了

 

4.4 BeanFactoryPostProcessor的執行

  即找到系統存在的BeanFactoryPostProcessor,同樣按照三級的形式根據優先級來執行。具體的邏輯也和上面詳細講的那個一級是一致的。

String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

//找到所有的BeanFactoryPostProcessor 並根據其級別進行歸類
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);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
//清除緩存
beanFactory.clearMetadataCache();

 

  到此,refresh方法中的兩個重要方法第一個   invokeBeanFactoryPostProcessors,已經完成,而其中的ConfigurationClassPostProcessor(也就是BeanDefinitionRegistryPostProcessor的一種)負責了最為核心的容器類加載,也就是主要分析的類也分析完成。(詳細的類解析過程篇幅問題放在下章)

  

 

 

總結

  本文主要分為了兩個部分,創建Spring應用上下文,和執行了其refresh方法中的invokeBeanFactoryPostProcessors方法。

  創建應用上下文的同時也會創建一個DefaultListableBeanFactory,這個也是靜態代理的體現。而在執行ApplicationContext的構造函數時,會創建一個AnnotatedBeanDefinitionReader,而這個類中會有一個BeanDefinitionRegistry屬性,並將我們一些必須的BeanDefinition添加進去,例如最為核心的  ConfigurationClassPostProcessor也就是在這個時候被添加進去的。

 

  執行invokeBeanFactoryPostProcessors方法則主要分為三個步驟

  • 執行所有傳入的BeanFactoryPostProcessor(如果為BeanFactoryPostProcessor)的postProcessBeanDefinitionRegistry方法

  • 找到BeanFactory中所有的BeanDefinitionRegistryPostProcessor類型的類並按照三級標准執行(實現了PriorityOrdered接口,實現了Ordered接口,啥都沒實現 );

  • 找到BeanFactory中所有的BeanFactoryPostProcessor類型的類並按照三級標准執行(實現了PriorityOrdered接口,實現了Ordered接口,啥都沒實現 );

  而其第二步則執行了核心的ConfigurationClassPostProcessor,並且是以最優先級執行,該processer會加載系統中所有需要加入容器的類,並且會解析所有的Configuration class

 

  

 

  

 

 

 

 

 

 

  

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM