Springboot 自動裝配原理探索

官網介紹

先來看看官網是怎么定義這個自動裝配的~

可以看到這里說,當你引入了某個 jar 依賴包時,Springboot 會嘗試根據這個依賴去自動配置 Spring 應用程序。

而且這里還說明了,你應該在 一個配置類 @Configuration 上選擇 @EnableAutoConfiguration 和 @SpringBootApplication 這其中的一個注解,來讓自動配置生效.

那么,知道這些信息后,我們就開始愉快地看源碼環節了~ 沖沖沖!

對了,探索的 Springboot 版本為 2.4.5

@SpringBootApplication

來到 @SpringBootApplication 注解中,可以發現它是一個組合注解,除了前面四個基本的元注解外,還有下面這三個 @SpringBootConfiguration , @EnableAutoConfiguration ,@ComponentScan

源碼如圖

@SpringBootConfiguration

我們先來看這第一個注解,如圖,可以發現它其實是一個 @Configuration 注解,@Configuration 注解的作用是將其作為一個配置類,來配置 Spring 的上下文,相當于 Spring 的 XML 配置文件中的 <beans>

源碼如圖

@ComponentScan

這個的作用就是 掃描指定路徑下的組件,并加入到 IOC 容器 中,相當于Spring 的 XML 配置文件中的 <context:component-scan/>

源碼如圖

可以發現它里面有一個 @Repeatable(ComponentScans.class) 注解,表示可重復使用@ComponentScan 注解

注意,這里會按照我們自定義的方式去排除一些類,具體是通過實現 TypeFilter 接口并重寫 match 方法來實現 。

小細節

這里還有個點要注意下~

AutoConfigurationExcludeFilter 會檢查配置類,如果該配置類和 META-INF/spring.factories 文件中的 EnableAutoConfiguration 對應的配置類一樣的話,會被排除掉~

@EnableAutoConfiguration

終于,來到本文的重點了

看到它的名字就知道它就是這個 自動配置 的主角了

源碼如圖

可以發現它是一個組合注解

先來看看這個注解1 @AutoConfigurationPackage

@AutoConfigurationPackage

從名字就可以看出它是一個 自動配置包路徑 的注解

源碼如圖

從這段注釋我們可以發現,當沒有配置這個 basePackages 或者 basePackageClasses 時,這個類就會自動將該注解所在的包作為基本路徑進行注冊

接著,我們再來看看這個框框里的內容~ @Import(
AutoConfigurationPackages.Registrar.class)

@Import

先來看看這個注解的作用吧

源碼如圖

可以發現它的作用也很簡單,就是導入組件,比如常見的 @Configuration 類或者ImportSelector 和
ImportBeanDefinitionRegistrar 的實現類,或者其他一些常規的組件如 @Component ,@Service 等等

Registrar

繼續看看這個 @Import(
AutoConfigurationPackages.Registrar.class) ,可以發現該注解導入的是 Registrar 類 , 那么我們繼續探索下,看看它干了什么~

源碼如圖

從該類的注解可以看出,它的作用是通過
ImportBeanDefinitionRegistrar **來保存這個基本包的路徑的 **


那么,講完第一點 ,我們簡單了解到這個 @AutoConfigurationPackage 就是用來配置基本包 ,我們接著再來看看第二點,這個 @Import(
AutoConfigurationImportSelector.class) 注解。

我們可以發現它導入了
AutoConfigurationImportSelector 類。

AutoConfigurationImportSelector

看這個名稱,可以大概知道它是一個 組件選擇器

關鍵步驟介紹

process

這個方法在獲取這些 Import 類時會被調用,具體可以看結尾的流程圖~

getAutoConfigurationEntry

獲取自動配置實體類 ,里面還有本文的重點~

getCandidateConfigurations

來到這里,可以發現它調用到這個 SpringFactoriesLoader ,這里就不得不提下這個 Springboot 的 SPI 機制了,另外它和我們上文(服務發現機制SPI居然是破壞者?! )中提到的 Java Spi 有什么不同呢 ?

再繼續往下看一下~

Springboot SPI機制

老規矩,看一眼注釋先 哈哈

spring.factories 文件

舉個栗子

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

可以發現它加載的是 META-INF/spring.factories 這個文件 ,相比 java 的 META-INF/services ,有以下的不同點:

  1. 從名字上就可以發現很大的不同( 一個是 factories 文件,一個是以接口全名命名的文件 )。
  2. spring.factories 以一個聚合的作用,把相應的接口和實現類以 key = value 形式展現在 spring.factories 文件中。
  3. spring.factories 中的所有配置項會加載到我們的緩存中,以 Map<String,List<String>> 形式存儲,但不是所有的都會被實例化,被加載到 IOC 容器中,除了必要的類外( EventPublishingRunListener 等 ),還有滿足特定條件下的自動配置類會被加載到 IOC 容器中

滿足特定條件 ? 比如有沒有使用到這個依賴( pom 中的 starter)

自動配置類 ? 指以 AutoConfiguration 結尾的那些類

可以發現這種按需實現的機制比java的一股腦實現靈活多了~

實例解析

比如 這里從 spring.factories 文件中加載了130個自動配置類

但是實際使用中,經過過濾后只有這 30 個了

這里還根據 優先級 做了一些排序~

自動裝配流程圖

這里只摘了一些關鍵步驟~ ,具體流程太長了 ,得從 SpringApplication 源碼中的 refreshContext(context); 這里就先不介紹啦,后面有時間再寫一下分享下這個 [[Springboot源碼的啟動過程]]

同顏色的類名和方法塊對應~

圖中左下角的 processImports 方法,就是將這些自動配置類進行實例化,包括配置類里面的 @Import , @Bean 等 ,一步步加載到 Spring 的 IOC 容器中。

總結

一. Springboot 的自動裝配很重要的一點就是,就是要在配置類上開啟 @EnableAutoConfiguration 或者 @SpringBootApplication 注解,來讓自動配置生效

二. 自動配置的核心是 Springboot 的 SPI 機制 ,以及組件選擇器
AutoConfigurationImportSelector,具體是通過其中的 getAutoConfigurationEntry 方法來獲取 SPI 中的自動配置類并進行過濾,最后通過 processImports 將配置類加載到 IOC 容器中,完成自動配置

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 如果我們想要使用傳統意義上的 Spring 應用,那么需要配置大量的 xml 文件才可以啟動,而且隨著項目的...
    小梁同學jxy閱讀 307評論 1 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,592評論 28 53
  • 信任包括信任自己和信任他人 很多時候,很多事情,失敗、遺憾、錯過,源于不自信,不信任他人 覺得自己做不成,別人做不...
    吳氵晃閱讀 6,222評論 4 8
  • 步驟:發微博01-導航欄內容 -> 發微博02-自定義TextView -> 發微博03-完善TextView和...
    dibadalu閱讀 3,167評論 1 3
  • 回這一趟老家,心里多了兩個疙瘩。第一是堂姐現在談了一個有婦之夫,在她的語言中感覺,她不打算跟他有太長遠的計劃,這讓...
    安九閱讀 3,525評論 2 4