一線大牛帶你深入解析AutoConfiguration源碼
AutoConfiguration lmportSelector源碼解析
@EnableAutoConfiguration 的關(guān)鍵功能是通過@Import 注解導(dǎo)入的 ImportSelector 來完成的從 源 代碼得知@lmport(
AutoConfigurationlmportSelector.class) 是@EnableAutoConfiguration 注 解 的 組成部分 , 也是自動(dòng)配置功能的核心實(shí)現(xiàn)者 。
@Ilmport(
AutoConfigurationlmportSele-ctor.class)又可以分為兩部分:
@Ilmport 和對(duì)應(yīng)的 ImportSelector。
本節(jié)重點(diǎn)講解@lmport 的基本使用方法和ImportSelector 的實(shí)現(xiàn)類
AutoConfigurationlmportSelector。
@Import 注解
@lmport 注解位于 spring-context 項(xiàng)目內(nèi),主要提供導(dǎo)入配置類的功能。
為什么要專門講解@lmport 的功能及使用呢?如果查看 Spring Boot 的源代碼,我們會(huì)發(fā)現(xiàn)大量的 EnableXXX 類都使用了該注解。了 解@lmport 注解的基本使用方法,能夠幫助我們更好地進(jìn)行源代碼的閱讀和理解。
@lmport 的源碼如下。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy. RUNTIME)
@Documented
public @interface Import {
Class>[] value();
}@lmport 的作用和 xml 配置中
ImportBeanDefinitionRegistrar 的類,還可以通過@lmport 導(dǎo)入普通的 POJO(將其注冊(cè)成Spring Bean,導(dǎo)入 POJO 需要 Spring 4.2 以上版本)。
關(guān)于@lmport 導(dǎo)入@Configuration 注解類和 POJO 的功能比較簡單和常見,就不再展開介紹了。下面重點(diǎn)介紹 ImportSelector 接口的作用。
ImportSelector 接口
@Import 的許多功能都需要借助接口 ImportSelector 來實(shí)現(xiàn),ImportSelector 決定可引入哪些@Configuration。ImportSelector 接口源碼如下。
public interface ImportSelector
String[] selectImports (AnnotationMetadata importingClassMetadata);
}ImportSelector 接口只提供了一個(gè) 參數(shù)為 AnnotationMetadata 的方法,返回的結(jié)果為一個(gè)字符串?dāng)?shù)組。其中參數(shù) AnnotationMetadata 內(nèi)包含了被@lmport 注解的類的注解信息。在selectlmports 方法內(nèi)可根據(jù)具體實(shí)現(xiàn)決定返回哪些配置類的全限定名,將結(jié)果以字符串?dāng)?shù)組的形式返回。
如果實(shí)現(xiàn)了接口 ImportSelector 的類的同時(shí)又實(shí)現(xiàn)了以下 4 個(gè) Aware 接口,那么 Spring 保證 在 調(diào) 用 ImportSelector 之 前 會(huì) 先 調(diào) 用 Aware 接 口 的 方 法 。這 4 個(gè) 接 口 為 :
EnvironmentAware 、 BeanFactoryAware 、 BeanClassLoaderAware 和 ResourceLoaderAware.
在
AutoConfigurationlmportSelector 的源代碼中就實(shí)現(xiàn)了這 4 個(gè)接口,部分源代碼及 Aware的全限定名代碼如下。
import org. springframework. beans. factory . BeanClassLoaderAware;
import org. springframework . beans . factory . BeanFactoryAware;
import org. springframework. context. EnvironmentAware;
import org. springframework. context. ResourceLoaderAware;
import org. springframework. context . annotation.DeferredImportSelector;
import org. springframework . core . Ordered;
public class AutoConfigurat ionImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanF actoryAware, EnvironmentAware, Ordered{
。。。}在.上面的源代碼中,
AutoConfigurationlmportSelector 并沒有 直接實(shí)現(xiàn) ImportSelector 接口,而是實(shí)現(xiàn)了它的子接口 DeferredIlmportSelector。
DeferredlmportSelector 接口與 ImportSelector 的區(qū)別是,前者會(huì)在所有的@Configuration類加載完成之后再加載返回的配置類,而 ImportSelector 是在加載完@Configuration 類之前先去加載返回的配置類。
DeferredlmportSelector 的加載順序可以通過@Order 注解或?qū)崿F(xiàn) Ordered 接口來指定。同時(shí),DeferredlmportSelector 提供了新的方法 getlmportGroup()來跨 DeferredlmportSelector實(shí)現(xiàn)自定義 Configuration 的加載順序。
AutoConfigurationlmportSelector 功能概述
下面我們通過圖 2-3 所示的流程圖來從整體上了解
AutoConfigurationlmportSelector 的核心功能及流程,然后再對(duì)照代碼看具體的功能實(shí)現(xiàn)。圖 2-3 中省略了外部通過@Import 注解調(diào)用該類的部分。

當(dāng)
AutoConfigurationlmportSelector 被@lmport 注解引入之后,它的 slectmports 方法會(huì)被調(diào)用并執(zhí)行其實(shí)現(xiàn)的自動(dòng)裝配邏輯。讀者朋友需注意,seletmports 方法幾乎涵蓋了組件自動(dòng)裝配的所有處理邏輯。
AhtonfiruriomoprSelelereleltiports 方法源代碼如下:
@Override
public String[ ] selectImports (AnnotationMetadata annotationMetadata) {
//檢查自動(dòng)配置功能是否開肩,默認(rèn)為開啟
if (!isEnabled(annotat ionMetadata)) {
return NO_ IMPORTS;
//加戴自動(dòng)配置的元信息,配置文件為類路徑中 META-INF 目錄下的
// spring-autoconfigure -metadata. properties 文件
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMe
tadataLoader
. loadMetadata(this . beanClassLoader);
//封裝將被引入的自動(dòng)配置信息
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry
autoConfigurationMetadata, annotationMetadata) ;
//返回符合條件的配置類的全限定名數(shù)組
return StringUtils. toStringArray(autoConfigurationEntry. getConfigurations
());
}
protected AutoConfigurationEntry getAutoConfigurat ionEntry(
AutoConfigurat ionMetadata autoConfi gurationMetadata,
Annotat ionMetadata annotationMetadata) {
if (!isEnabled( annotationMetadata)) {
return EMPTY_ ENTRY;
}
AnnotationAttributes attributes = getAttributes ( annotat ionMetadata);
//通過 SpringFactoriesLoader 類提供的方法加戴類路徑中 META-INF 目錄下的
// spring . factories 文件中針對(duì) EnableAutoConfigurat ion 的往冊(cè)配置類
List configurations = getCandidateConfigurations (annotationMetadata,
attributes);
//對(duì)獲得的注冊(cè)配置類集合進(jìn)行去重處理,防止多個(gè)項(xiàng)目引入同樣的配置類 configurations =
removeDuplicates( configurations);
//獲得炷解中被 excLude.或 excLudeName 所排除的類的集合
Set exclusions = getExclusions ( annotationMetadata, attributes);
//檢查被排除類是否可實(shí)例化,是否被自動(dòng)注冊(cè)配置所使用,不符合條件則拋出異常
checkExcludedClasses (configurations, exclusions);
//從自動(dòng)配置類集合中去除被排除的類
configurations . removeAll(exclusions);
//檢查配置類的注解是否符合 spring . factories 文件中 AutoConfigurat ionImportFilter.指定
的注解檢查條件
configurations = filter( configurations, autoConfigurationMetadata);
//將篩選完成的配置類和排查的配置類構(gòu)建為事件類, 并傳入監(jiān)聽器。監(jiān)聽器的配置在
Fspring . factories 文件中,通過 AutoConf igurat ionImportL istener 指定
fireAutoConfigurationImportEvents( configurations, exclusions);
return new AutoConfigurat ionEntry(configurations, exclusions);
} 通過圖 2-3 和上述代碼,我們從整體層面了解了
AutoConfigurationlmportSelector 的概況及操作流程,后文將對(duì)這些流程進(jìn)行細(xì)化拆分,并通過閱讀源代碼來分析 Sprng Boot 是如何實(shí)現(xiàn)自動(dòng)加載功能的。
@Enable AutoConfiguration 自動(dòng)配置開關(guān)
檢查自動(dòng)配置是否開啟的代碼位于
AutoConfiguratinmportSelector的selectmpots方法第一段中。如果開啟自動(dòng)配置功能,就繼續(xù)執(zhí)行后續(xù)操作;如果未開啟,就返回空數(shù)組。代碼如下。
@Override
public String[]
selectImports (AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotat ionMetadata)) {
return NO_ IMPORTS;
}
}
該方法主要使用 isEnabled 方法來判斷自動(dòng)配置是否開啟,代碼如下。
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass() == AutoConfigurationImportSelector . class) {
return getEnvironment(). getProperty(
EnableAutoConfiguration. ENABLED_ _OVERRIDE_ PROPERTY, Boolean.class,
true);
}
return true;}通過 isEnabled 方法可以看出,如果當(dāng)前類為
AutoConfigurationlmportSelector 程序會(huì)從環(huán)境中獲取 key 為 EnableAutoConfiguration.ENABL ED_ OVERRIDE PROPERTY 的配置,該常量的值為 spring.boot.enableautoconfiguration.如果獲取不到該屬性的配置,isEnabled默認(rèn)為 true,也就是默認(rèn)會(huì)使用自動(dòng)配置。如果當(dāng)前類為其他類,直接返回 true。
如果想覆蓋或重置.ENABLED_ _OVERRIDE_ PROPERTY 的配置,可獲取該常量的值,并在 aplication.properties 或 plcatin.ym|中針對(duì)此參數(shù)進(jìn)行配置。以 application.properties配置關(guān)閉自動(dòng)配置為例,代碼如下。
spring.boot.enableautoconfiguration-false本文給大家講解的內(nèi)容是AutoConfigurationlmportSelector功能概述和AutoConfiguration自動(dòng)配置開關(guān)
下篇文章給大家講解的是AutoConfiguration加載元數(shù)據(jù)配置和加載自動(dòng)配置組件;
覺得文章不錯(cuò)的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
感謝大家的支持!
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號(hào)里找我,我等你哦。
