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-INFspring.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); } }