@EnableAutoConfiguration的说明

 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);
    }
}
posted @ 2020-01-02 14:53  mufeng07  阅读(2141)  评论(0编辑  收藏  举报