




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第SpringBoot示例分析講解自動化裝配機(jī)制核心注解目錄1.自動化裝配介紹2.SpringBoot自動化配置UML圖解3.SpringBoot自動化配置核心注解分析3.1@Inherited3.2@SpringBootConfiguration3.3@EnableAutoConfiguration3.4@ComponentScan3.5@ConfigurationPropertiesScan3.6@AutoConfigurationImportSelector3.7@AutoConfigurationPackages4.總結(jié)
1.自動化裝配介紹
SpringBoot針對mvc做了大量封裝,簡化開發(fā)者的使用,內(nèi)部是如何管理資源配置,Bean配置,環(huán)境變量配置以及啟動配置等?實(shí)質(zhì)是SpringBoot做了大量的注解封裝,比如@SpringBootApplication,同時(shí)采用Spring4框架的新特性@Conditional基于條件的Bean創(chuàng)建管理機(jī)制來實(shí)現(xiàn);
實(shí)際的工作場景中是復(fù)雜多樣的,有些項(xiàng)目需要不同的組件,比如REDIS、MONGODB作緩存;RABBITMQ、KAFKA作消息隊(duì)列;有些項(xiàng)目運(yùn)行環(huán)境不同,比如JDK7、JDK8不同版本,面對眾多復(fù)雜的需求,又要做到最大化支持,SpringBoot是如何管理實(shí)現(xiàn)的,這就依賴Conditional功能,基于條件的自動化配置。
2.SpringBoot自動化配置UML圖解
SpringBootApplication是我們所常用熟知的注解,它是一個組合注解,依賴多個注解,共同實(shí)現(xiàn)SpringBoot應(yīng)用功能,以下為所有依賴的UML圖解,我們圍繞這些注解深入研究,看下具體的實(shí)現(xiàn)。
3.SpringBoot自動化配置核心注解分析
SpringBootApplication注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters={@Filter(type=FilterType.CUSTOM,classes=TypeExcludeFilter.class),
@Filter(type=FilterType.CUSTOM,classes=AutoConfigurationExcludeFilter.class)})
@ConfigurationPropertiesScan
public@interfaceSpringBootApplication{
*需要排除的自動化配置,根據(jù)類名進(jìn)行排除,比如MongoAutoConfiguration,JpaRepositoriesAutoConfiguration等
@AliasFor(annotation=EnableAutoConfiguration.class)
Class[]exclude()default{};
*需要排除的自動化配置,根據(jù)名稱進(jìn)行排除
@AliasFor(annotation=EnableAutoConfiguration.class)
String[]excludeName()default{};
*指定需要掃描的包路徑,參數(shù)填寫包名
@AliasFor(annotation=ComponentScan.class,attribute="basePackages")
String[]scanBasePackages()default{};
*指定需要掃描的包路徑
@AliasFor(annotation=ComponentScan.class,attribute="basePackageClasses")
Class[]scanBasePackageClasses()default{};
*Bean方法的動態(tài)代理配置,如果沒有采用工廠方法,可以標(biāo)記為false,采用cglib代理。
@AliasFor(annotation=Configuration.class)
booleanproxyBeanMethods()defaulttrue;
}
3.1@Inherited
java.lang.annotation.@Inherited注解,從包名可以看出為JDK自帶注解,作用是讓子類能夠繼承父類中引用Inherited的注解,但需注意的是,該注解作用范圍只在類聲明中有效;如果是接口與接口的繼承,類與接口的繼承,是不會生效。
3.2@SpringBootConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods=false)
public@interfaceSpringBootConfiguration{
*Bean方法的動態(tài)代理配置
@AliasFor(annotation=Configuration.class)
booleanproxyBeanMethods()defaulttrue;
}
這是配置型處理注解,可以看到內(nèi)部源碼引用了@Configuration注解,
自身沒有太多的實(shí)現(xiàn),那為什么還需要再包裝?官方給出的解釋是對Spring的@Configuration的擴(kuò)展,
用于實(shí)現(xiàn)SpringBoot的自動化配置。proxyBeanMethods屬性默認(rèn)為true,作用是對bean的方法是否開啟代理方式調(diào)用,默認(rèn)為true,如果沒有采用工廠方法,可以設(shè)為false,通過cglib作動態(tài)代理。
3.3@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public@interfaceEnableAutoConfiguration{
//設(shè)置注解支持重載的標(biāo)識
StringENABLED_OVERRIDE_PROPERTY="spring.boot.enableautoconfiguration";
*排除自動化配置的組件,如MongoAutoConfiguration,JpaRepositoriesAutoConfiguration等
Class[]exclude()default{};
*排除自動化配置的組件,根據(jù)名稱設(shè)置
String[]excludeName()default{};
}
用于管理開啟SpringBoot的各種自動化配置注解,如datasource,mongodb,redis等,也是spring-boot-autoconfigure工程的核心注解。
AutoConfigurationPackage
它的主要作用是掃描主程序同級及下級的包路徑所有Bean與組件注冊到SpringIoc容器中。
Import
它可以把沒有聲明配置的類注冊到SpringIoc容器中管理引用。導(dǎo)入的AutoConfigurationImportSelector類實(shí)現(xiàn)BeanClassLoaderAware、ResourceLoaderAware、EnvironmentAware等接口,管理類裝載器,資源裝載器及環(huán)境配置等,是一個負(fù)責(zé)處理自動化配置導(dǎo)入的選擇管理器。在下面【@AutoConfigurationImportSelector剖析】進(jìn)行詳解。
3.4@ComponentScan
這是我們在Spring下面常用的一個注解,它可以掃描Spring定義的注解,如@Componment,@Service等,常用的屬性有basePackages掃描路徑,includeFilters包含路徑過濾器,excludeFilters排除路徑過濾器,lazyInit是否懶加載等,能夠非常靈活的掃描管理需要注冊組件。
3.5@ConfigurationPropertiesScan
作用是掃描指定包及子包路徑下面的ConfigurationProperties注解,管理工程配置屬性信息。主要屬性為basePackages掃描路徑,支持多個路徑,數(shù)組形式;basePackageClasses屬性也可以具體到包下面的類,
支持多個配置。
3.6@AutoConfigurationImportSelector
AutoConfigurationImportSelector實(shí)現(xiàn)DeferredImportSelector、BeanClassLoaderAware、ResourceLoaderAware、BeanFactoryAware、EnvironmentAware、Ordered接口,為自動化配置的核心處理類,主要負(fù)責(zé)自動化配置規(guī)則的一系列處理邏輯:
/**
*{@linkDeferredImportSelector}tohandle{@linkEnableAutoConfiguration
*auto-configuration}.Thisclasscanalsobesubclassedifacustomvariantof
*{@linkEnableAutoConfiguration@EnableAutoConfiguration}isneeded.
*@authorPhillipWebb
*@authorAndyWilkinson
*@authorStephaneNicoll
*@authorMadhuraBhave
*@since1.3.0
*@seeEnableAutoConfiguration
publicclassAutoConfigurationImportSelectorimplementsDeferredImportSelector,BeanClassLoaderAware,
ResourceLoaderAware,BeanFactoryAware,EnvironmentAware,Ordered{
}
講解幾個技術(shù)點(diǎn):
getCandidateConfigurations方法
protectedListStringgetCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){
ListStringconfigurations=SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations,"NoautoconfigurationclassesfoundinMETA-INF/spring.factories.Ifyou"
+"areusingacustompackaging,makesurethatfileiscorrect.");
returnconfigurations;
}
該方法是獲取所有SpringBoot聲明定義的自動化配置類。
看下具體有哪些信息:
這些實(shí)際是配置在Spring-boot-autoconfigure工程下的META-INF/spring.factories文件中:
看到這里,我們應(yīng)該可以明白,為什么AOP,RABBIT,DATASOURCE,REIDS等組件SPRINGBOOT都能幫我們快速配置實(shí)現(xiàn),其實(shí)它內(nèi)部遵循SPI機(jī)制,已經(jīng)把自動化配置做好了封裝。
AutoConfigurationGroup類
它是AutoConfigurationImportSelector的內(nèi)部類,實(shí)現(xiàn)了DeferredImportSelector.Group、BeanClassLoaderAware、BeanFactoryAware、ResourceLoaderAware接口,是一個重要的核心類。主要作用是負(fù)責(zé)自動化配置條目信息的記錄,排序,元數(shù)據(jù)處理等。它通過getImportGroup方法獲取返回,該方法實(shí)現(xiàn)DeferredImportSelector的接口。
privatestaticclassAutoConfigurationGroup
implementsDeferredImportSelector.Group,BeanClassLoaderAware,BeanFactoryAware,ResourceLoaderAware{
//記錄注解的元數(shù)據(jù)
privatefinalMapString,AnnotationMetadataentries=newLinkedHashMap();
//記錄自動化配置條目,放入集合
privatefinalListAutoConfigurationEntryautoConfigurationEntries=newArrayList();
//設(shè)置bean的類加載器
privateClassLoaderbeanClassLoader;
//設(shè)置bean工廠信息
privateBeanFactorybeanFactory;
//設(shè)置資源加載器信息
privateResourceLoaderresourceLoader;
//設(shè)置自動化配置的元數(shù)據(jù)記錄
privateAutoConfigurationMetadataautoConfigurationMetadata;
}
屬性主要定義了一些自動化配置類目信息、BEAN工廠、類和資源加載器信息。entries條目有22條,具體內(nèi)容如下:
里面是主要的自動化配置類的元數(shù)據(jù)信息,autoConfigurationEntries屬性就是具體的自動化配置條目。這些主要自動化類配置是Springboot幫助我們實(shí)現(xiàn)mvc的核心功能,如請求分發(fā),文件上傳,參數(shù)驗(yàn)證,編碼轉(zhuǎn)換等功能。還有一部分是定制條件自動化配置類,
autoConfigurationMetadata元數(shù)據(jù)內(nèi)容較多,包含各種組件,根據(jù)環(huán)境配置和版本不同,這里可以看到共有705個:
由于SpringBoot支持眾多插件,功能豐富,數(shù)量較多;這里存在些疑問,這里面的元數(shù)據(jù)和上面的entries條目都是AutoConfiguration自動化配置類,那有什么區(qū)別?其實(shí)這里面的,都是基于條件的自動化配置。
我們就拿KafkaAutoConfiguration來看:
可以看到注解ConditionalOnClass,意思是KafkaAutoConfiguration生效的前提是基于KafkaTemplate類的初始化成功,這就是定制條件,也就是基于條件的自動化配置類,雖然有七百多個,但其實(shí)是根據(jù)工程實(shí)際用到的組件,才會觸發(fā)加載對應(yīng)的配置。有關(guān)Conditional基于條件的自動化配置實(shí)現(xiàn)原理,在下面我們再作深入研究。
繼續(xù)看AutoConfigurationImportSelector內(nèi)部類的selectImports方法:
@Override
publicIterableEntryselectImports(){
if(this.autoConfigurationEntries.isEmpty()){
returnCollections.emptyList();
//將所有自動化條目根據(jù)配置的Exclusion條件作過濾,并轉(zhuǎn)換為SET集合
SetStringallExclusions=this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
//SET集合,記錄所有需要處理的自動化配置
SetStringprocessedConfigurations=this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
//兩個SET,做交集過濾,排除不需要的配置
processedConfigurations.removeAll(allExclusions);
//最后進(jìn)行排序處理
returnsortAutoConfigurations(processedConfigurations,getAutoConfigurationMetadata()).stream()
.map((importClassName)-newEntry(this.entries.get(importClassName),importClassName))
.collect(Collectors.toList());
}
該方法是針對autoConfigurationEntries自動化配置條目做過濾,根據(jù)指定的排除規(guī)則處理;再根據(jù)設(shè)置的啟動的優(yōu)先級做排序整理。從代碼中可以看到,先獲取所有的allExclusions排除配置信息,再獲取所有需要處理的processedConfigurations配置信息,然后做過濾處理,最后再調(diào)用sortAutoConfigurations方法,根據(jù)order順序做排序整理。
AutoConfigurationImportSelector內(nèi)部類的process方法:
@Override
publicvoidprocess(AnnotationMetadataannotationMetadata,DeferredImportSelectordeferredImportSelector){
Assert.state(deferredImportSelectorinstanceofAutoConfigurationImportSelector,
()-String.format("Only%simplementationsaresupported,got%s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
//獲取自動化配置條目
AutoConfigurationEntryautoConfigurationEntry=((AutoConfigurationImportSelector)deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(),annotationMetadata);
//記錄獲取的條目
this.autoConfigurationEntries.add(autoConfigurationEntry);
for(StringimportClassName:autoConfigurationEntry.getConfigurations()){
//放入成員變量entries中
this.entries.putIfAbsent(importClassName,annotationMetadata);
}
該方法是掃描獲取autoConfigurationEntries自動化配置條目信息。
annotationMetadata參數(shù):
為注解元數(shù)據(jù),有也就是被@SpringBootApplication修飾的類信息,在這里就是我們的啟動入口類信息。
deferredImportSelector參數(shù):
通過@EnableAutoConfiguration注解定義的@Import的類,也就是AutoConfigurationImportSelector對象。根據(jù)配置,會加載指定的beanFactory、classLoader、resourceLoader和environment對象。
AutoConfigurationImportSelector內(nèi)部類的getAutoConfigurationEntry方法:
protectedAutoConfigurationEntrygetAutoConfigurationEntry(AutoConfigurationMetadataautoConfigurationMetadata,
AnnotationMetadataannotationMetadata){
//1、判斷是否開對應(yīng)注解
if(!isEnabled(annotationMetadata)){
returnEMPTY_ENTRY;
//2、獲取注解定義的屬性
AnnotationAttributesattributes=getAttributes(annotationMetadata);
//3、獲取符合規(guī)則的SpringBoot內(nèi)置的自動化配置類,并做去重處理
ListStringconfigurations=getCandidateConfigurations(annotationMetadata,attributes);
configurations=removeDuplicates(configurations);
//4、做排除規(guī)則匹配,過濾處理
SetStringexclusions=getExclusions(annotationMetadata,attributes);
checkExcludedClasses(configurations,exclusions);
configurations.removeAll(exclusions);
configurations=filter(configurations,autoConfigurationMetadata);
//5、觸發(fā)自動導(dǎo)入處理完成事件
fireAutoConfigurationImportEvents(configurations,exclusions);
returnnewAutoConfigurationEntry(configurations,exclusions);
}
該方法主要作用是獲取SpringBoot內(nèi)置的自動化條目,例AopAutoConfiguration等,該方法會調(diào)用上面講解的getCandidateConfigurations方法。主要步驟邏輯如下:
判斷是否開啟元注解掃描,對應(yīng)屬性為spring.boot.enableautoconfiguration,默認(rèn)情況下,是開啟自動配置。獲取定義的注解屬性,跟蹤內(nèi)部源碼,里面會返回exclude和excludeName等屬性。獲取符合規(guī)則的SpringBoot內(nèi)置的自動化配置,并做去重處理,也就是我們上面講解的getCandidateConfigurations方法,從中我們就可以理解其中的關(guān)聯(lián)關(guān)系。做排除規(guī)則檢查與過濾處理,根據(jù)上面第2個步驟獲取的exclude等屬性以及配置屬性spring.autoconfigure.exclude做過濾處理。觸發(fā)自動導(dǎo)入完成事件,該方法內(nèi)部邏輯正常處理完成才會觸發(fā),會調(diào)用AutoConfigurationImportListener監(jiān)聽器做通知處理。
3.7@AutoConfigurationPackages
AutoConfigurationPackages是EnableAutoConfiguration上的另一個核心注解類,官方解釋為:
Indicatesthatthepackagecontainingtheannotatedclassshouldberegistered
意思是包含該注解的類,所在包下面的class,都會注冊到SpringIoc容器中。對應(yīng)源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public@interfaceAutoConfigurationPackage{
Import注解,導(dǎo)入AutoConfigurationPackages抽象類下面的內(nèi)部靜態(tài)類Registrar,研究Registrar實(shí)現(xiàn)原理:
Registrar實(shí)現(xiàn)ImportBeanDefinitionRegistrar、DeterminableImports接口,它負(fù)責(zé)存儲從@AutoConfigurationPackage注解掃描到的信息。源碼如下:
staticclassRegistrarimplementsImportBeanDefinitionRegistrar,DeterminableImports{
//注冊BEAN的定義信息
@Override
publicvoidregisterBeanDefinitions(AnnotationMetadatametadata,BeanDefinitionRegistryregistry){
register(registry,newPackageImport(metadata).getPackageName());
//決定是否導(dǎo)入注解中的配置內(nèi)容
@Override
publicSetObjectdetermineImports(AnnotationMetadatametadata){
returnCollections.singleton(newPackageImport(metadata));
}
這里面主要涉及到PackageImport類,它是AutoConfigurationPackages的內(nèi)部私有靜態(tài)類,主要是記錄導(dǎo)入的報(bào)名信息,源碼如下:
/**
*Wrapperforapackageimport.
privatestaticfinalclassPackageImport{
privatefinalStringpackageName;
//構(gòu)造方法,記錄注解內(nèi)容
PackageImport(AnnotationMetadatametadata){
this.packageName=ClassUtils.getPackageName(metadata.getClassName());
//獲取指定包名稱
publicStringgetPackageName(){
returnthis.packageName;
//重載父類比較邏輯,根據(jù)包名判斷
@Override
publicbooleanequals(Objectobj){
if(obj==null||getClass()!=obj.getClass()){
returnfalse;
returnthis.packageName.equals(((PackageImport)obj).packageName);
//重載hash標(biāo)識,以包名的HASH值為準(zhǔn)
@Override
publicinthashCode(){
returnthis.packageName.hashCode();
//重載toString,打印內(nèi)容
@Override
publicStringtoString(){
return"PackageImport"+this.packageName;
}
內(nèi)部斷點(diǎn)跟蹤的話,可以看到它記錄的是我們啟動類所在的包名。這也就是為什么不需要指定掃描包路徑,也會加載啟動類所在包下面的JavaConfig配置信息。
回到上面Registrar的registerBeanDefinitions方法,內(nèi)部調(diào)用的是register方法:
它是處理記錄AutoConfigurationPackages掃描包信息,源碼如下:
publicstaticvoidregister(BeanDefinitionRegistryregistry,String...packageNames){
//判斷是否包含BEAN定義信息,如果包含,更新packageNames信息
if(registry.containsBeanDefinition(BEAN)){
BeanDefinitionbeanDefinition=registry.getBeanDefinition(BEAN);
ConstructorArgumentValuesconstructorArguments=beanDefinition.getConstructorArgumentValues();
constructorArguments.addIndexedArgumentValue(0,addBasePackages(constructorArguments,packageNames));
//如果registry中
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 插畫培訓(xùn)合同協(xié)議書
- 種子種植合同協(xié)議書
- 線上直播合同協(xié)議書
- 手機(jī)售后合同協(xié)議書
- 車位互換合同協(xié)議書
- 借用合同協(xié)議書模板
- 活動合同終止協(xié)議書
- 外墻膩?zhàn)雍贤瑓f(xié)議書
- 轉(zhuǎn)讓郵箱合同協(xié)議書
- 入股養(yǎng)殖合同協(xié)議書
- 創(chuàng)業(yè)投資管理智慧樹知到期末考試答案章節(jié)答案2024年武漢科技大學(xué)
- 工程倫理案例與分析
- (高清版)WST 227-2024 臨床檢驗(yàn)項(xiàng)目標(biāo)準(zhǔn)操作程序編寫要求
- 2024年江蘇省常州市新北區(qū)常州外國語學(xué)校中考一模英語試題(無答案)
- T-CACM 1218-2019 中醫(yī)骨傷科臨床診療指南 股骨粗隆間骨折
- 可口可樂灌裝封口線機(jī)器人工作站控制系統(tǒng)設(shè)計(jì)
- 漂珠檢測報(bào)告
- 永不言敗不放棄不拋棄
- 一年級下冊動物王國開大會課件
- 《用戶畫像-大數(shù)據(jù)時(shí)代的買家思維營銷》讀書筆記
- 高原疾病急救培訓(xùn)課件
評論
0/150
提交評論