日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

springboot是怎么實現自動配置的?

作者:不隨意的風 更新時間: 2022-09-05 編程語言

一、springboot是對spring框架做的一系列優化,減少了大量繁瑣的配置,并提供了內置web服務器,讓程序運行更快。

1.springboot起步依賴:簡單的說,起步依賴就是將具備某種功能的坐標打包到一起,并提供一些默認的功能。

2.自動配置Spring以及第三方功能:

SpringBoot是基于約定的,所以很多配置都有默認值,但如果想使用自己的配置替換默認配置的話,就可以使用application.properties或者application.yml(application.yaml)進行配置。

首先打開spring boot項目在springboot的引導類有一個@SpringBootApplication注解:

@Target({ElementType.TYPE}) //修飾類或接口、枚舉
@Retention(RetentionPolicy.RUNTIME)//注解在源碼,class文件中存在且運行時可以通過反射機制獲取到
@Documented//可以在api文檔顯示
@Inherited//子類可以繼承該注解
@SpringBootConfiguration //配置類
@EnableAutoConfiguration//開啟自動裝配
@ComponentScan //掃描 (不指明包名則默認范圍自己所在包及其子類下)
(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

除了基本的元注解外,還有兩個。其中:@@SpringBootConfiguration的里面核心是

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration//spring的配置類
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

表明啟動類其實也是一個配置類。還有一個是@EnableAutoConfiguration,根據名稱翻譯就是開啟自動配置。它里面包含了如下注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

可以看到@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})注解加起來就是實現了自動配置的關鍵。

@import:提供可以顯式的從其他地方加載配置類的方式。有三種方式:

1.普通類

2.接口importSelector的實現類

3.接口importBeanDefintionRegistart的實現類

自動配置就是用來第二種方式。importSelector接口中有一個selectImports方法,返回值是一個字符串數組,數組中的每個元素就是將要被導入的配置類的全限定的類名。

@Import導入了一個AutoConfigurationImportSelector.class的選擇器。那么如何根據這個選擇器來實現自動配置?

spring框架在底層中使用了springfactories機制,它是Java SPI(SPI(Service Provider Interface),是JDK內置的一種服務提供發現機制,可以用來啟用框架擴展和替換組件,主要是被框架的開發人員使用,比如java.sql.Driver接口,其他不同廠商可以針對同一接口做出不同的實現,MySQL和PostgreSQL都有不同的實現提供給用戶,而Java的SPI機制可以為某個接口尋找服務實現。Java中SPI機制主要思想是將裝配的控制權移到程序之外,在模塊化設計中這個機制尤其重要,其核心思想就是解耦)的延續,可以借助它來實現自動配置的功能。他的核心邏輯是從Classpath中讀取到Jar包中的配置文件META-IF/spring.factories,然后根據知道的key從配置文件中解析出對應的value值。?

回到正題:在AutoConfigurationImportSelector.class中有selectImports方法里面調用了getAutoConfigurationEntry(annotationMetadata)方法,它是自動配置的入口。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);//自動配置的入口
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

源碼如下:

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            //1.獲取annotationMetadata的注解@EnableAutoConfiguration的屬性
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//2.從資源文件中spring.factories中獲取EnableAutoConfiguration對應的所有類
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            //3.通過在注解@EnableAutoConfiguration設置exclude的相關屬性,可以指定排除的自動配置類
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            //4.根據@Conditional(滿足條件是觸發)來判斷是否排除某些自動配置類
            configurations = this.getConfigurationClassFilter().filter(configurations);
            //5.觸發AutoConfiguration導入相關的事件
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

?核心是第2步:拿到所有全限定類名

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//從spring.factorie找出所有的類
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

總結下流程:從selectimports方法開始:

1.通過ClassLoader去獲取classpath中的配置文件spring.factories

?

2.在spring.factories文件里,篩選出以EnableAutoConfiguration為key的配置類(

?3.再根據@Conditional過濾掉不必要的自動配置類

原文鏈接:https://blog.csdn.net/weixin_71419462/article/details/126336534

欄目分類
最近更新