Spring Boot快速入门 -> Spring Boot 自动配置原理分析(三)

前言:不忘初心,寻找最初的编程快感!

Spring Boot 自动配置原理

时序图

在这里插入图片描述

分析

  1. @SpringBootApplication注册程序入口,是@SpringBootConfiguration丶@EnableAutoConfiguration
    和@ComponentScan的并集
@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {

        SpringApplication application = new SpringApplication(MySpringBootApplication.class);

        application.run();
    }
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
  1. @SpringBootConfiguration继承至@Configuration,二者差不多功能一致,标注当前类是配置类,
    并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。
@SpringBootConfiguration
public class SpringBootConfigurationTestConfig {
    @Bean
    public String testConfig(){
        return "testConfig......";
    }
}
@SpringBootApplication
public class MySpringBootApplication {

    public static void main(String[] args) {

        SpringApplication application = new SpringApplication(MySpringBootApplication.class);

        ConfigurableApplicationContext context = application.run();

        System.out.println(context.getBeanFactory().getBean("testConfig"));
    }
}
  1. 最主要的还是@EnableAutoConfiguration,打开自动配置,可以通过设置注解的excludeName属性或者通过spring.autoconfigure.exclude配置项来指定不需要自动配置的项目。
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}
  1. AutoConfigurationImportSelector实现了selectImports() 方法,用来筛选被@Import的Configuration类(减去exclude等)
  • org.springframework.boot.autoconfigure.AutoConfigurationImportSelector类图:
    在这里插入图片描述
  • Spring boot发现注解中存在@Import(ImportSelector)的情况,就会创建一个相应的ImportSelector对象, 并调用其方法 public String[] selectImports(AnnotationMetadata annotationMetadata),如下是相关源码解析:
protected boolean isEnabled(AnnotationMetadata metadata) {
        return this.getClass() == AutoConfigurationImportSelector.class ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true;
    }
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
    	//根据spring-boot-autoconfigure包下的spring-autoconfigure-metadate.properties中的配置加载配置元数据
    	//loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
        //
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
    	//获取@EnableAutoConfiguration配置类名称及exclude属性
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        //从spring-boot-autoconfigure包里面META-INF/spring.factories加载配置类的名称
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        //去重处理,LinkedHashSet去重
        configurations = this.removeDuplicates(configurations);
        //获取自动配置排除类
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        //检查排除类是否是auto-configuration classes
        this.checkExcludedClasses(configurations, exclusions);
        //去除自动配置排除类
        configurations.removeAll(exclusions);
        //过滤掉配置未配置@OnClassCondition的自动配置类,当检测存在输入的类时候,该配置类生效,否则将不被实例化;
        //AutoConfigurationImportFilter -> FilteringSpringBootCondition.match -> OnClassCondition.getMatchOutcome
        configurations = this.filter(configurations, autoConfigurationMetadata);
        //激活配置ConditionEvaluationReportAutoConfigurationImportListener.onAutoConfigurationImportEvent
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        //返回AutoConfigurationEntry配置信息
        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
}

小结

Spring Boot的自动化配置提供了十分方便的开发方式,但任何东西都可能有其两面性的存在,“欲思其利,必虑其害,欲思其成,必虑其败”,实际使用中还得多注意细枝末节,要做到更灵活丶更高效地使用手中的利剑;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值