springboot的自动配置

1. 原由

​ 使用springboot也有些时间,一直很好奇它如何作到自动配置的,因此查阅了相关资料而且学习了相关内容,才写了这篇文章。java

2. 分析

​ ①第一步咱们从它的启动配置类(XxxApplication)收起,咱们进入到他的@SpringBootApplication注解。
在这里插入图片描述spring

​ ②咱们能够看到以下代码,因为咱们须要找到致使它自动配置的,因此锁定了@EnableAutoConfiguration注解,那么就能够进入这个注解。springboot

@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 {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

在这里插入图片描述

​ ③ 咱们看到了以下代码,因为这是一个接口,而它的实现类咱们又很差肯定,因此咱们只好从注解入手,因为@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited等都是元注解,咱们能够从@AutoConfigurationPackage,@Import({AutoConfigurationImportSelector.class})中找到咱们想要的,根据它的中文意思咱们能够从@Import({AutoConfigurationImportSelector.class})(自动有选择的导入配置)出发,毕竟不是全部的配置都会都如,而导入那些配置根据项目中使用了那些starter决定。
在这里插入图片描述app

​ ④点入第三步提到的注解,进入这个类根据方法名咱们能够猜想是和这个方法相关,经过阅读这个代码,咱们能够猜想是和getAutoConfigurationEntry这个方法有关,因此不妨点进去。学习

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata =        AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

​ ⑤因为咱们须要的配置Config,因此大体能够判定是和这个代码有关联List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); ,因此不妨进到这个getCandidateConfigurations方法中去。this

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

​ ⑥通过第五步,咱们能够看到以下代码code

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;
    }

不妨看这部分代码,List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); ,它的意思是一个加载器经过加载某个工厂得到配置的List,所以咱们在进入到这个的实现是没有必要的,能够从参数考虑,因此锁定在第一个参数,点进入能够看到以下代码。xml

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

看到这里可能仍是会疑惑?为啥就自动配置了,其实咱们这个方法(loadFactoryNames)是从一个配置文件中读取内容,它的键是EnableAutoConfiguration,而这个配置文件是在如图所示的文件中。blog

在这里插入图片描述
在这里插入图片描述

⑥打开上述文件,根据上一步的键找它的值,如图就是springboot配置类,那么项目启动时是否是全部的配置都起做用吗?不妨进入到某个配置类查看便可。如图所示的@ConditionalOnMissingBean注解表示项目的容器是否有这个bean,若是没有这个配置类就不会其做用,另外咱们只要在仔细看这个类首先进行了初始化,以后它会从配置文件(application.xml或者application.yml)中获取值。
在这里插入图片描述接口

注:若有错误,欢迎指出。

相关文章
相关标签/搜索