TcaplusDB君 · 行業新聞彙編(7月26日)
阿新 • • 發佈:2021-07-28
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就可以實現智慧的自動配置。
SpringFactoriesLoader中載入配置,SpringFactoriesLoader屬於Spring框架私有的一種擴充套件方案,其主要功能就是從指定的配置檔案META-INF/spring.factories載入配置,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查詢的Key,獲取對應的一組@Configuration類//從這裡可以看出該類實現很多的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; } ... }
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包