【十九】Spring IOC 總結之啓動時定位資源和BeanDefinition載入、解析、註冊(SpringBoot 掃啓動類所在包、starter、@Import)

源碼調試以spring boot 1.5.8.release爲例

Spring IOC容器初始化主要有以下幾個步驟

1、資源定位:找到配置文件。

2、BeanDefinition載入和解析

3、BeanDefinition註冊

4、實例化bean和依賴注入  (不在本篇討論範圍,該內容總結請看【十八】Spring IOC 總結之getBean主流程和各個擴展點總結

而這一系列的操作種的前三步在SpringBoot中都是在AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中完成的,該方法的源碼導讀請看以前寫的這篇:【四】Spring源碼分析之啓動主流程---AbstractApplicationContext的refresh方法  只是對該方法做了一個簡單介紹而已。

這個invokeBeanFactoryPostProcessors方法寫的很噁心,裏面是調用了ConfigurationClassPostProcessor的processConfigBeanDefinitions方法真正完成的資源定位、BeanDefinition載入和解析、BeanDefinition註冊,該方法源碼導讀請看以前寫的這篇:【八】Spring源碼分析之掃描註冊Bean----ConfigurationClassPostProcessor的processConfigBeanDefinitions方法

本篇主要是總結一下SpringBoot怎麼做定位資源,主要的3中定位資源的方式

這裏涉及到常規的Spring Boot項目中有3種定位方式:

1.掃主類(就是有註解@SpringBootApplication這個類)所在包的路徑

2.SPI擴展機制實現的自動裝配(比如各種starter)

3.@Import註解指定的類。

 上面已經提到入口是ConfigurationClassPostProcessor的processConfigBeanDefinitions

這裏面是調用ConfigurationClassParser#parse(Set<BeanDefinitionHolder> configCandidates)方法來做的定位

該方法中主要是兩個事:

1.繼續調用本類的其他parse方法做定位,最終的邏輯是在doProcessConfigurationClass方法中。

該方法包含了兩種定位資源的方式
掃描springboot的有@SpringBootApplication註解的那個啓動類所在的路徑和對啓動類的@Import註解的處理

2.processDeferredImportSelectors方法加載默認的配置(對springboot項目來說這裏就是自動裝配的入口了)

一、ConfigurationClassParser#doProcessConfigurationClass方法

該方法就是掃描springboot的有@SpringBootApplication註解的那個啓動類所在的路徑

1.首先遞歸處理啓動類的內部類,我們一般不會在啓動類寫內部類,就不debug這個了

2.對 @PropertySource 註解的屬性配置進行處理,這個我也沒有觸發到

解析該註解並將該註解指定的properties配置文件中的值存儲到Spring的 Environment中,Environment接口提供方法去讀取配置文件中的值,參數是properties文件中定義的key值。

3.對 @ComponentScan 註解進行處理(該註解在@SpringBootApplication註解中)

1.掃描啓動類所在的包,找到所有的@Component註解修飾的bean,並註冊到BeanDefinitionMap中

這裏就是從basePackage中掃描類並解析成ScannedGenericBeanDefinition然後註冊

主要邏輯的實現入口在ClassPathBeanDefinitionScanner#doScan

2.檢查該bean是否是ConfigurationClass(是否有configuration/component兩個註解)

如果是,遞歸查找該類相關聯的配置類。

(相關的配置類:比如@Configuration中的@Bean定義的bean。或者在有@Component註解的類上繼續存在@Import註解)

4.遞歸處理啓動類中的@Import,並加載該註解指定的配置類。

這裏說一下,@SpringBootApplication註解中包含@EnableAutoConfiguration註解,

而@EnableAutoConfiguration註解

包含@Import(EnableAutoConfigurationImportSelector.class)和@AutoConfigurationPackage這兩個註解是重點

5.處理啓動類中的@ImportResource註解,這裏沒有觸發

6.處理啓動類中的@Bean註解,這裏沒有觸發

7.處理啓動類實現的接口方法,並沒有觸發

8.處理啓動類的父類,並沒有觸發

二、processDeferredImportSelectors方法加載默認的配置

該方法就是通過啓動類的@Import加載各個jar下META-INF/spring.factories的自動配置類並註冊

對springboot項目來說這裏就是自動裝配的入口了

1.該方法裏面會調用EnableAutoConfigurationImportSelector的父類AutoConfigurationImportSelector的selectImports方法

1.獲取所有的自動配置類(META-INF/spring.factories中配置的key爲org.springframework.boot.autoconfigure.EnableAutoConfiguration的類)

2.排除的自動裝配類(springboot的主類上 @SpringBootApplication(exclude = {com.demo.starter.config.DemoConfig.class})指定的排除的自動裝配類)

3.過濾掉不需要裝配的類。過濾的邏輯有很多,比如我們常用的@ConditionXXX註解

4.返回需要自動配置類的全名

2.然後用ConfigurationClassParser#doProcessConfigurationClass方法講這些自動配置類加載並註冊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章