SpringBoot自动配置原理


自动配置原理

关键注解@SpringBootApplication

点击进入@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 {
}

其中包含@EnableAutoConfiguration注解意为开启自动配置(顺便一提:@ComponentScan注解
这个注解会扫描和加了这个注解的类在同一包和子包下的所有组件即:Controllerservice等,为我们省去了写xml配置文件的过程),再点击进入@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 {};

}

这个注解有2个方法: exclude 和 excludeName,在@SpringBootApplication中可以通过使用这两个方法来指明我们不想自动注入的类

比如:我们不想让springBoot自动配置数据源(springBoot默认HikariCP连接池),这样可以自己注入数据源,达到切换连接池的目的

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ForumServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ForumServiceApplication.class, args);
    }
}

@Import(AutoConfigurationImportSelector.class),@import注解表示引入指定类型的bean,即AutoConfigurationImportSelector,SpringBoot为我们自动注入的
bean全部通过它来读取,点击进入AutoConfigurationImportSelector源码

public class AutoConfigurationImportSelector
        implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
        BeanFactoryAware, EnvironmentAware, Ordered {

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

    protected AutoConfigurationEntry getAutoConfigurationEntry(
            AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), 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;
    }

}

getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);

AutoConfigurationImportSelector通过getAutoConfigurationEntry这个方法获取到需要自动注入的类,getAutoConfigurationEntry又调用了
getCandidateConfigurations(annotationMetadata,attributes),getCandidateConfigurations调用SpringFactoriesLoader类的静态方法,进入
SpringFactoriesLoader中,这个类是spring-core包中的

public final class SpringFactoriesLoader {

    /**
     * The location to look for factories.
     * <p>Can be present in multiple JAR files.
     */
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
}

自动配置核心文件

通过源码注释可以看到 FACTORIES_RESOURCE_LOCATION,并且位置为META-INF/spring.factories, spring.factories是本文重点

spring.facoties

部分spring.factories内容:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
下面所有的自动配置类将被springBoot自动注入,通过spring.factories我们可以自定义自动配置类,实现springboot容器启动时自动注入的效果


文章作者: Ubi-potato
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ubi-potato !
评论
  目录