springboot版本為2.0.7
@SpringBootApplication引入@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 {}; }
@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都加載到當前SpringBoot創建並使用的IoC容器。
借助於Spring框架原有的一個工具類:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自動配置功效才得以大功告成!
在AutoConfigurationImportSelector類中可以看到通過 SpringFactoriesLoader.loadFactoryNames()
把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一個xxxAutoConfiguration文件都加載到容器中,spring.factories文件里每一個xxxAutoConfiguration文件一般都會有下面的條件注解:
@ConditionalOnClass : classpath中存在該類時起效
@ConditionalOnMissingClass : classpath中不存在該類時起效
@ConditionalOnBean : DI容器中存在該類型Bean時起效
@ConditionalOnMissingBean : DI容器中不存在該類型Bean時起效
@ConditionalOnSingleCandidate : DI容器中該類型Bean只有一個或@Primary的只有一個時起效
@ConditionalOnExpression : SpEL表達式結果為true時
@ConditionalOnProperty : 參數設置或者值一致時起效
@ConditionalOnResource : 指定的文件存在時起效
@ConditionalOnJndi : 指定的JNDI存在時起效
@ConditionalOnJava : 指定的Java版本存在時起效
@ConditionalOnWebApplication : Web應用環境下起效
@ConditionalOnNotWebApplication : 非Web應用環境下起效
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { // 從配置文件中加載 AutoConfigurationMetadata AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); // 獲取注解的屬性值 AnnotationAttributes attributes = this.getAttributes(annotationMetadata); // 獲取所有候選配置類EnableAutoConfiguration // 使用了內部工具使用SpringFactoriesLoader,查找classpath上所有jar包中的 // META-INF\spring.factories,找出其中key為 // org.springframework.boot.autoconfigure.EnableAutoConfiguration // 的屬性定義的工廠類名稱。 // 雖然參數有annotationMetadata,attributes,但在 AutoConfigurationImportSelector 的 // 實現 getCandidateConfigurations()中,這兩個參數並未使用 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); // 去重 configurations = this.removeDuplicates(configurations); // 應用 exclusion 屬性 Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); // 對於不屬於AutoConfiguration的exclude報錯 this.checkExcludedClasses(configurations, exclusions); // 從configurations去除exclusions configurations.removeAll(exclusions); // 應用過濾器AutoConfigurationImportFilter, // 對於 spring boot autoconfigure,定義了一個需要被應用的過濾器 : // org.springframework.boot.autoconfigure.condition.OnClassCondition, // 此過濾器檢查候選配置類上的注解@ConditionalOnClass,如果要求的類在classpath // 中不存在,則這個候選配置類會被排除掉 configurations = this.filter(configurations, autoConfigurationMetadata); // 現在已經找到所有需要被應用的候選配置類 // 廣播事件 AutoConfigurationImportEvent this.fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations); } }