SpringBoot 版本 : 2.2.1.RELEASE
關(guān)鍵詞:@EnableAutoConfiguration,/META-INF/spring.factories,
/META-INF/spring-autoconfigure-metadata.properties
注:本文主要講解一些比較重要的關(guān)鍵步驟,不能面面俱到,若有疑問,隨時(shí)保持溝通
- 大家都知道,SpringBoot 六大特性:
- 創(chuàng)建獨(dú)立的Spring應(yīng)用
- 嵌入式Web容器(可以以可執(zhí)行jar方式運(yùn)行,不需要部署WAR文件)
- 提供固化的 "starter",簡化構(gòu)建配置
- 當(dāng)條件滿足時(shí)自動(dòng)地裝配Spring或第三方庫
- 提供運(yùn)維特性(Production-Ready)特性,如指標(biāo)信息(Metrics)、健康檢查、外部化配置。
- 不需要XML配置
- 其中有一項(xiàng)為自動(dòng)裝配功能,自動(dòng)裝配功能總體來說由 @EnableXXX注解 + @Import , 再配合@Conditional注解可以實(shí)現(xiàn)條件自動(dòng)裝配,在SpringBoot中核心注解為@EnableAutoConfiguration
1. @EnableAutoConfiguration注解
- 通常情況下,springBoot應(yīng)用啟動(dòng)類不會(huì)直接標(biāo)注此注解,而是通過@SpringBootApplication注解來實(shí)現(xiàn):image.png
總結(jié):在啟動(dòng)類上加上 @EnableAutoConfiguration 注解 或者@SpringBootApplication即可實(shí)現(xiàn)自動(dòng)裝配,推薦使用 @SpringBootApplication這個(gè)組合注解。
2. @EnableAutoConfiguration注解實(shí)現(xiàn)自動(dòng)裝配原理
- 依照 @EnableXXX的驅(qū)動(dòng)設(shè)計(jì),@EnableAutoConfiguration 必然也是按照 @Import 配合 ImportSelector或者 ImportBeandefinetionRegistrar 接口編程的套路,查看@EnableAutoConfiguration注解源碼:image.pngimage.png
- 此時(shí)相信讀者已經(jīng)知道大致的脈絡(luò)了,那么我們就重點(diǎn)分析一下 AutoConfigurationImportSelector 這個(gè) ImportSelector實(shí)現(xiàn)。
- 正常情況下,若類實(shí)現(xiàn)了 ImportSelector接口,則會(huì)回調(diào)其相對于的 selectImports方法,但是我們通類的關(guān)系圖發(fā)現(xiàn)AutoConfigurationImportSelector 直接實(shí)現(xiàn)的是 DeferredImportSelector,而這個(gè) ImportSelector 如下: image.pngimage.pngimage.pngimage.pngimage.pngimage.png
"遞歸以上描述"
,肯定會(huì)恍然大悟,若是熟悉的話可以直接跳過????,然后分析:
- getAutoConfigurationMetadata()
- SprinBoot框架層幫忙做的自動(dòng)裝配元數(shù)據(jù)
- AutoConfigurationEntry entry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata)
- AnnotationAttributes attributes = getAttributes(annotationMetadata) 獲取@EnableAutoConfiguration標(biāo)注類的元信息。
- List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes):由于返回的結(jié)果是候選類的集合,跟蹤調(diào)用鏈會(huì)發(fā)現(xiàn):image.pngimage.png
返回的是 key = org.springframework.boot.autoconfigure.EnableAutoConfiguration對應(yīng)的values值,這些values即是SpringBoot默認(rèn)的自動(dòng)裝配類,所以有時(shí)候讀者閱讀源碼時(shí),發(fā)現(xiàn)某些類莫名其妙的被裝載到Spring容器中了,一部分原因可能是這個(gè)地方搞的鬼。
- configurations = removeDuplicates(configurations)
- 移除重復(fù)定義的配置類( 利用set集合的不可重復(fù)性 )
- Set<String> exclusions = getExclusions(annotationMetadata, attributes)
- 獲取排除類名單,排除類可通過 exclude = {A.class.B.class}屬性來排除指定的配置類。
- configurations = filter(configurations, autoConfigurationMetadata)
-
經(jīng)過去重和排除過的配置類再執(zhí)行過濾操作,過濾代碼:image.png
-
①中 調(diào)用的是 SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader),也是在spring.factories中獲取 AutoConfigurationImportFilter類型的過濾器,此處默認(rèn)有
image.png -
②中 分別執(zhí)行配置類的match方法,由于 OnBeanCondition、OnClassCondition、OnWebApplicationCondition 均繼承自 FilteringSpringBootCondition,match方法如下:
image.pngimage.png -
通過上面三個(gè)子類的方法實(shí)現(xiàn) ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata),此處拿OnBeanCondition類來分析:
image.png配置類.ConditionalOnBean
的元信息,即在元數(shù)據(jù)配置文件中的 values。image.png
以 RedisCacheConfiguration為例,其 "conditionOnBean" 如下:image.pngimage.png 解析到這里,自動(dòng)裝配的底層實(shí)現(xiàn)細(xì)節(jié)基本已經(jīng)說完了,底層實(shí)現(xiàn)稍微有點(diǎn)晦澀難懂,但是只要掌握關(guān)鍵性的類及注解的作用之后,再去了解源碼基本上就可以手到擒來了。
總結(jié):自動(dòng)裝配的流程
- 添加 @SpringBootApplication 注解或者 @EnableAutoConfiguration
- 通過 SpringFactoriesLoader.loadFactoryNames(...) 獲取自動(dòng)裝配類,執(zhí)行一系列的去重、排除等操作,然后通過過濾,通過判斷當(dāng)前類加載器是否是加載元數(shù)據(jù)的類加載器來決定 @ConditiionOnXXX 注解的裝配過程。
- 自動(dòng)裝配是SpringBoot的元數(shù)據(jù)配置文件(spring-autoconfigure-metadata.properties)中的配置類的選擇性加載的過程。
- ? 文章要是勘誤或者知識點(diǎn)說的不正確,歡迎評論,畢竟這也是作者通過閱讀源碼獲得的知識,難免會(huì)有疏忽!
- ? 要是感覺文章對你有所幫助,不妨點(diǎn)個(gè)關(guān)注,或者移駕看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
- ? 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處!