1. 程式人生 > 其它 >TcaplusDB君 · 行業新聞彙編(7月26日)

TcaplusDB君 · 行業新聞彙編(7月26日)

1、從@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) })
    public @interface SpringBootApplication {
    
        @AliasFor(annotation = EnableAutoConfiguration.class)
        Class<?>[] exclude() default {};
        @AliasFor(annotation = EnableAutoConfiguration.class)
        String[] excludeName() default {};
    //根據包路徑掃描
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
        String[] scanBasePackages() default {};
    //直接根據class類掃描
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
        Class<?>[] scanBasePackageClasses() default {};
    }
  • 初看@SpringBootApplication有很多的註解組成,其實歸納就是一個"三體"結構,重要的只有三個Annotation:
  • @SpringBootConfiguration(@SpringBootConfiguration實質就是一個@Configuration)
    @EnableAutoConfiguration
    @ComponentScan
  • 也就是說我們在開發的時候,加上上面的上個註解會等同於加上@SpringBootApplication註解

  

(1)@SpringBootConfiguration註解

  這個註解實際上就是代表了一個配置類,相當於一個beans.xml檔案

(2)@ComponentScan

  @ComponentScan的功能其實就是自動掃描並載入符合條件的元件或bean定義,最終將這些bean定義載入到容器中

3)@EnableAutoConfiguration

  在spring中有關於@Enablexxx的註解是開啟某一項功能的註解,比如@EnableScheduling表示開啟spring的定時任務。其原理是藉助@Import的幫助,

  將所有符合自動配置條件的bean定義載入到Ioc容器

  • EnableAutoConfiguration代表開啟springboot的自動裝配
  • @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 {};
    }
  • 從原始碼中可以知道,最關鍵的要屬@Import(EnableAutoConfigurationImportSelector.class),藉助EnableAutoConfigurationImportSelector, @EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都載入到當前SpringBoot建立並使用的IoC容器。 同時藉助於Spring框架原有的一個工具類:SpringFactoriesLoader,@EnableAutoConfiguration就可以實現智慧的自動配置。
    //從這裡可以看出該類實現很多的xxxAware和DeferredImportSelector,所有的aware都優先於selectImports
    //方法執行,也就是說selectImports方法最後執行,那麼在它執行的時候所有需要的資源都已經獲取到了
    public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    ...
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            } else {
    //1載入META-INF/spring-autoconfigure-metadata.properties檔案
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
    //2獲取註解的屬性及其值(PS:註解指的是@EnableAutoConfiguration註解)
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
    //3.在classpath下所有的META-INF/spring.factories檔案中查詢org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,並將其封裝到一個List中返回
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
    //4.對上一步返回的List中的元素去重、排序
                configurations = this.removeDuplicates(configurations);
    //5.依據第2步中獲取的屬性值排除一些特定的類
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
    //6對上一步中所得到的List進行過濾,過濾的依據是條件匹配。這裡用到的過濾器是
    //org.springframework.boot.autoconfigure.condition.OnClassCondition最終返回的是一個ConditionOutcome[]
    //陣列。(PS:很多類都是依賴於其它的類的,當有某個類時才會裝配,所以這次過濾的就是根據是否有某個
    //class進而決定是否裝配的。這些類所依賴的類都寫在META-INF/spring-autoconfigure-metadata.properties檔案裡)
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return StringUtils.toStringArray(configurations);
            }
        }
      protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
            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;
        }
    
    ...
    }
    SpringFactoriesLoader中載入配置,SpringFactoriesLoader屬於Spring框架私有的一種擴充套件方案,其主要功能就是從指定的配置檔案META-INF/spring.factories載入配置,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查詢的Key,獲取對應的一組@Configuration類
    public abstract class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static Map<String, List<String>> loadSpringFactories(


    總結

    @EnableAutoConfiguration作用就是從classpath中搜尋所有的META-INF/spring.factories配置檔案,

    並將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)例項化為對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,

    然後彙總為一個並載入到IoC容器。這些功能配置類要生效的話,會去classpath中找是否有該類的依賴類(也就是pom.xml必須有對應功能的jar包才行)並且配置類裡面注入了預設屬性值類,

    功能類可以引用並賦預設值。生成功能類的原則是自定義優先,沒有自定義時才會使用自動裝配類。

    所以功能類能生效需要的條件:(1)spring.factories裡面有這個類的配置類(一個配置類可以建立多個圍繞該功能的依賴類)(2)pom.xml裡面需要有對應的jar包