




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第SpringBoot自動(dòng)配置原理詳解@SpringBootConfiguration(里面就是@Configuration,標(biāo)注當(dāng)前類為配置類,其實(shí)只是做了一層封裝改了個(gè)名字而已)
@EnableAutoConfiguration(開啟自動(dòng)配置)
@ComponentScan(包掃描)
注:@Inherited是一個(gè)標(biāo)識(shí),用來修飾注解,如果一個(gè)類用上了@Inherited修飾的注解,那么其子類也會(huì)繼承這個(gè)注解
我們下面逐一分析這3個(gè)注解作用
3.1.1@SpringBootConfiguration
我們繼續(xù)點(diǎn)@SpringBootConfiguration進(jìn)去查看源碼如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public@interfaceSpringBootConfiguration{
@AliasFor(
annotation=Configuration.class
booleanproxyBeanMethods()defaulttrue;
@Configuration標(biāo)注在某個(gè)類上,表示這是一個(gè)springboot的配置類??梢韵蛉萜髦凶⑷虢M件。
3.1.2@ComponentScan
@ComponentScan:配置用于Configuration類的組件掃描指令。
提供與SpringXML的context:component-scan元素并行的支持。
可以basePackageClasses或basePackages來定義要掃描的特定包。如果沒有定義特定的包,將從聲明該注解的類的包開始掃描。
3.1.3@EnableAutoConfiguration
@EnableAutoConfiguration顧名思義就是:開啟自動(dòng)導(dǎo)入配置
這個(gè)注解是SpringBoot的重點(diǎn),我們下面詳細(xì)講解
四、@EnableAutoConfiguration
我們點(diǎn)進(jìn)去看看該注解有什么內(nèi)容
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage//自動(dòng)導(dǎo)包
@Import({AutoConfigurationImportSelector.class})//自動(dòng)配置導(dǎo)入選擇
public@interfaceEnableAutoConfiguration{
StringENABLED_OVERRIDE_PROPERTY="spring.boot.enableautoconfiguration";
Class[]exclude()default{};
String[]excludeName()default{};
4.1@AutoConfigurationPackage
自動(dòng)導(dǎo)入配置包
點(diǎn)進(jìn)去查看代碼:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public@interfaceAutoConfigurationPackage{
String[]basePackages()default{};
Class[]basePackageClasses()default{};
@Import為spring的注解,導(dǎo)入一個(gè)配置文件,在springboot中為給容器導(dǎo)入一個(gè)組件,而導(dǎo)入的組件由AutoConfigurationPackages.class的內(nèi)部類Registrar.class執(zhí)行邏輯來決定是如何導(dǎo)入的。
4.1.1@Import({Registrar.class})
點(diǎn)Registrar.class進(jìn)去查看源碼如下:
staticclassRegistrarimplementsImportBeanDefinitionRegistrar,DeterminableImports{
Registrar(){
publicvoidregisterBeanDefinitions(AnnotationMetadatametadata,BeanDefinitionRegistryregistry){
//斷點(diǎn)
AutoConfigurationPackages.register(registry,(String[])(newAutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(newString[0]));
publicSetObjectdetermineImports(AnnotationMetadatametadata){
returnCollections.singleton(newAutoConfigurationPackages.PackageImports(metadata));
注:Registrar實(shí)現(xiàn)了ImportBeanDefinitionRegistrar類,就可以被注解@Import導(dǎo)入到spring容器里。
這個(gè)地方打斷點(diǎn)
運(yùn)行可以查看到(String[])(newAutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(newString[0])的值為com.ljw.springbootwork:當(dāng)前啟動(dòng)類所在的包名
結(jié)論:@AutoConfigurationPackage就是將主配置類(@SpringBootApplication標(biāo)注的類)所在的包下面所有的組件都掃描注冊(cè)到spring容器中。
4.2
@Import({AutoConfigurationImportSelector.class})
作用:AutoConfigurationImportSelector開啟自動(dòng)配置類的導(dǎo)包的選擇器,即是帶入哪些類,有選擇性的導(dǎo)入
點(diǎn)AutoConfigurationImportSelector.class進(jìn)入查看源碼,這個(gè)類中有兩個(gè)方法見名知意:
1.selectImports:選擇需要導(dǎo)入的組件
publicString[]selectImports(AnnotationMetadataannotationMetadata){
if(!this.isEnabled(annotationMetadata)){
returnNO_IMPORTS;
}else{
AutoConfigurationImportSelector.AutoConfigurationEntryautoConfigurationEntry=this.getAutoConfigurationEntry(annotationMetadata);
returnStringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
2.getAutoConfigurationEntry:根據(jù)導(dǎo)入的@Configuration類的AnnotationMetadata返回AutoConfigurationImportSelector.AutoConfigurationEntry
protectedAutoConfigurationImportSelector.AutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadataannotationMetadata){
if(!this.isEnabled(annotationMetadata)){
returnEMPTY_ENTRY;
}else{
AnnotationAttributesattributes=this.getAttributes(annotationMetadata);
//這打個(gè)斷點(diǎn),看看返回的數(shù)據(jù)
ListStringconfigurations=this.getCandidateConfigurations(annotationMetadata,attributes);
//刪除重復(fù)項(xiàng)
configurations=this.removeDuplicates(configurations);
SetStringexclusions=this.getExclusions(annotationMetadata,attributes);
//檢查
this.checkExcludedClasses(configurations,exclusions);
//刪除需要排除的依賴
configurations.removeAll(exclusions);
configurations=this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations,exclusions);
returnnewAutoConfigurationImportSelector.AutoConfigurationEntry(configurations,exclusions);
this.getCandidateConfigurations(annotationMetadata,attributes)這里斷點(diǎn)查看
configurations數(shù)組長度為133,并且文件后綴名都為**AutoConfiguration
結(jié)論:這些都是候選的配置類,經(jīng)過去重,去除需要的排除的依賴,最終的組件才是這個(gè)環(huán)境需要的所有組件。有了自動(dòng)配置,就不需要我們自己手寫配置的值了,配置類有默認(rèn)值的。
我們繼續(xù)往下看看是如何返回需要配置的組件的
4.2.1getCandidateConfigurations(annotationMetadata,attributes)
方法如下:
protectedListStringgetCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){
ListStringconfigurations=SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(),this.getBeanClassLoader());
Assert.notEmpty(configurations,"NoautoconfigurationclassesfoundinMETA-INF/spring.factories.Ifyouareusingacustompackaging,makesurethatfileiscorrect.");
returnconfigurations;
這里有句斷言:Assert.notEmpty(configurations,"NoautoconfigurationclassesfoundinMETA-INF/spring.factories.Ifyouareusingacustompackaging,makesurethatfileiscorrect.");
意思是:“在META-INF/spring.factories中沒有找到自動(dòng)配置類。如果您使用自定義包裝,請(qǐng)確保該文件是正確的。“
結(jié)論:即是要loadFactoryNames()方法要找到自動(dòng)的配置類返回才不會(huì)報(bào)錯(cuò)。
getSpringFactoriesLoaderFactoryClass()
我們點(diǎn)進(jìn)去發(fā)現(xiàn):this.getSpringFactoriesLoaderFactoryClass()返回的是EnableAutoConfiguration.class這個(gè)注解。這個(gè)注解和@SpringBootApplication下標(biāo)識(shí)注解是同一個(gè)注解。
protectedClassgetSpringFactoriesLoaderFactoryClass(){
returnEnableAutoConfiguration.class;
結(jié)論:獲取一個(gè)能加載自動(dòng)配置類的類,即SpringBoot默認(rèn)自動(dòng)配置類為EnableAutoConfiguration
4.2.2SpringFactoriesLoader
SpringFactoriesLoader工廠加載機(jī)制是Spring內(nèi)部提供的一個(gè)約定俗成的加載方式,只需要在模塊的META-INF/spring.factories文件,這個(gè)Properties格式的文件中的key是接口、注解、或抽象類的全名,value是以逗號(hào)“,“分隔的實(shí)現(xiàn)類,使用SpringFactoriesLoader來實(shí)現(xiàn)相應(yīng)的實(shí)現(xiàn)類注入Spirng容器中。
注:會(huì)加載所有jar包下的classpath路徑下的META-INF/spring.factories文件,這樣文件不止一個(gè)。
loadFactoryNames()
publicstaticListStringloadFactoryNames(ClassfactoryType,@NullableClassLoaderclassLoader){
ClassLoaderclassLoaderToUse=classLoader;
if(classLoaderToUse==null){
classLoaderToUse=SpringFactoriesLoader.class.getClassLoader();
StringfactoryTypeName=factoryType.getName();
returnloadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName,Collections.emptyList());
斷點(diǎn)查看factoryTypeName:
先是將EnableAutoConfiguration.class傳給了factoryType
然后StringfactoryTypeName=factoryType.getName();,所以factoryTypeName值為
org.springframework.boot.autoconfigure.EnableAutoConfiguration
loadSpringFactories()
接著查看loadSpringFactories方法的作用
privatestaticMapString,ListStringloadSpringFactories(ClassLoaderclassLoader){
//斷點(diǎn)查看
MapString,ListStringresult=cache.get(classLoader);
if(result!=null){
returnresult;
result=newHashMap();
try{
//注意這里:META-INF/spring.factories
EnumerationURLurls=classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while(urls.hasMoreElements()){
URLurl=urls.nextElement();
UrlResourceresource=newUrlResource(url);
Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);
for(Map.Entry,entry:properties.entrySet()){
StringfactoryTypeName=((String)entry.getKey()).trim();
String[]factoryImplementationNames=
StringUmaDelimitedListToStringArray((String)entry.getValue());
for(StringfactoryImplementationName:factoryImplementationNames){
//斷點(diǎn)
puteIfAbsent(factoryTypeName,key-newArrayList())
.add(factoryImplementationName.trim());
//Replacealllistswithunmodifiablelistscontaininguniqueelements
//去重,斷點(diǎn)查看result值
result.replaceAll((factoryType,implementations)-implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(),Collections::unmodifiableList)));
cache.put(classLoader,result);
catch(IOExceptionex){
thrownewIllegalArgumentException("Unabletoloadfactoriesfromlocation["+
FACTORIES_RESOURCE_LOCATION+"]",ex);
returnresult;
這里的FACTORIES_RESOURCE_LOCATION在上面有定義:META-INF/spring.factories
publicfinalclassSpringFactoriesLoader{
*Thelocationtolookforfactories.
*pCanbepresentinmultipleJARfiles.
publicstaticfinalStringFACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";
META-INF/spring.factories文件在哪里??
在所有引入的java包的當(dāng)前類路徑下的META-INF/spring.factories文件都會(huì)被讀取,如:
斷點(diǎn)查看result值如下:
該方法作用是加載所有依賴的路徑META-INF/spring.factories文件,通過map結(jié)構(gòu)保存,key為文件中定義的一些標(biāo)識(shí)工廠類,value就是能自動(dòng)配置的一些工廠實(shí)現(xiàn)的類,value用list保存并去重。
在回看loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName,Collections.emptyList());
因?yàn)閘oadFactoryNames方法攜帶過來的第一個(gè)參數(shù)為EnableAutoConfiguration.class,所以factoryType值也為EnableAutoConfiguration.class,那么factoryTypeName值為EnableAutoConfiguration。拿到的值就是META-INF/spring.factories文件下的key為
org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
getOrDefault當(dāng)Map集合中有這個(gè)key時(shí),就使用這個(gè)key值,如果沒有就使用默認(rèn)值空數(shù)組
結(jié)論:
loadSpringFactories()該方法就是從“META-INF/spring.factories”中加載給定類型的工廠實(shí)現(xiàn)的完全限定類名放到map中
loadFactoryNames()是根據(jù)SpringBoot的啟動(dòng)生命流程,當(dāng)需要加載自動(dòng)配置類時(shí),就會(huì)傳入org.springframework.boot.autoconfigure.EnableAutoConfiguration參數(shù),從map中查找key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,這些值通過反射加到容器中,之后的作用就是用它們來做自動(dòng)配置,這就是Sp
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 航空航天零部件高精度加工技術(shù)2025年市場前景與挑戰(zhàn)報(bào)告
- 葡萄酒行業(yè)產(chǎn)區(qū)特色品牌國際化:2025年全球市場機(jī)遇分析報(bào)告
- 2025屆滁州鳳陽縣聯(lián)考七下英語期末檢測(cè)試題含答案
- 2025年電商平臺(tái)內(nèi)容營銷與種草經(jīng)濟(jì)在電商區(qū)塊鏈技術(shù)應(yīng)用報(bào)告
- 2025年醫(yī)藥行業(yè)合規(guī)運(yùn)營策略與信息化建設(shè)深度分析報(bào)告
- 2025年BIM技術(shù)在建筑行業(yè)工程項(xiàng)目施工進(jìn)度調(diào)整與優(yōu)化報(bào)告
- 2025年醫(yī)藥企業(yè)研發(fā)外包(CRO)模式下的臨床試驗(yàn)數(shù)據(jù)安全報(bào)告
- 2025年醫(yī)藥流通行業(yè)供應(yīng)鏈優(yōu)化與成本控制策略分析報(bào)告
- 繼教培訓(xùn)課件模板
- 廣東省東莞市五校2025屆七年級(jí)英語第二學(xué)期期中學(xué)業(yè)水平測(cè)試模擬試題含答案
- 2023年杭州育才中學(xué)小升初語文考試真題卷含標(biāo)準(zhǔn)答案
- 2023年安徽六安市裕安區(qū)城鄉(xiāng)建設(shè)投資集團(tuán)有限公司招聘筆試題庫及答案解析
- 超市營業(yè)員聘用勞務(wù)合同書(2篇)
- GB/T 2832-1996陶管抗外壓強(qiáng)度試驗(yàn)方法
- GB/T 19974-2018醫(yī)療保健產(chǎn)品滅菌滅菌因子的特性及醫(yī)療器械滅菌過程的開發(fā)、確認(rèn)和常規(guī)控制的通用要求
- GB/T 17530.4-1998工業(yè)丙烯酸酯酸度的測(cè)定
- GB/T 10095.1-2008圓柱齒輪精度制第1部分:輪齒同側(cè)齒面偏差的定義和允許值
- 湖北省荊州市商投資區(qū)國有企業(yè)招聘考試《綜合基礎(chǔ)知識(shí)》國考真題
- 熱電公司設(shè)備標(biāo)志牌制作、懸掛標(biāo)準(zhǔn)
- 2022年XX中心學(xué)校教師“縣管校聘”工作實(shí)施方案
- 人教版七年級(jí)下冊(cè)數(shù)學(xué)《期末考試卷》(含答案)
評(píng)論
0/150
提交評(píng)論