Spring Boot 自动化配置原理

我们经常使用Spring Boot,是否知道Spring Boot自动化配置是怎么实现的呢?

一 初识自动化配置

Spring Boot自动化配置依赖于@EnableAutoConfiguration注解

该注解会在@SpringBootApplication中包含

该注解为一个复合注解包含了以下注解

@SpringBootConfiguration 标识该类是一个配置类

@EnableAutoConfiguration 开启自动化配置

@ComponentScan 扫描该类下的所有包配置的bean

springboot 写java自动化接口 springboot自动化配置原理_springboot filter

二 揭开自动化配置面纱

@EnableAutoConfiguration 今天我们主要关注的是这个注解

此注解为一个复合注解包含了@AutoConfigurationPackage 该注解会导入一个AutoConfigurationPackages

springboot 写java自动化接口 springboot自动化配置原理_springboot自动配置原理_02

该方法将主程序类所在包及所有子包下的组件到扫描到spring容器中完成项目包下组件的自动注册

至此我们完成了自动化配置中自己的组件的自动化配置,那么我们依赖的jar包自动化配置说怎么实现的呢,请继续往下看

springboot 写java自动化接口 springboot自动化配置原理_springboot原理_03

springboot 写java自动化接口 springboot自动化配置原理_springboot自动配置_04

三 深入自动化配置

我们继续回到EnableAutoConfiguration注解

springboot 写java自动化接口 springboot自动化配置原理_springboot自动配置_05

该注解包含2个属性:

exclude:根据类排除不使用的自动配置;

excludeName:根据类名排除不使用的自动配置;

并导入了AutoConfigurationImportSelector类 该类的核心方法为getCandidateConfigurations通过该方法即可获取到(spring-boot-2.1.3.RELEASE.jar/META-INF/spring.factories) 下的配置文件,该文件为spring boot自动化配置的配置文件,至此我们获取到的是所有的自动化配置类,那么spring boot的按需导入是怎么实现的呢,请继续往下看

springboot 写java自动化接口 springboot自动化配置原理_springboot 获取配置文件中的值_06

springboot 写java自动化接口 springboot自动化配置原理_springboot 获取配置文件中的值_07

springboot 写java自动化接口 springboot自动化配置原理_springboot filter_08

springboot 写java自动化接口 springboot自动化配置原理_springboot 获取配置文件中的值_09


因为spring boot是按需配置所以我们还需要根据引入的依赖筛选出需要的配置,核心方法如下

protected AutoConfigurationEntry getAutoConfigurationEntry(
   AutoConfigurationMetadata autoConfigurationMetadata,
   AnnotationMetadata annotationMetadata) {
        //判断是否开启自动配置
  if (!isEnabled(annotationMetadata)) { 
   return EMPTY_ENTRY;
  }
  AnnotationAttributes attributes = getAttributes(annotationMetadata);
       //获取自动配置文件和配置
  List configurations = getCandidateConfigurations(annotationMetadata,
    attributes);//删除重复项
  configurations = removeDuplicates(configurations);//获取排除的自动化配置
  Set exclusions = getExclusions(annotationMetadata, attributes);//检查排除的自动化配置
  checkExcludedClasses(configurations, exclusions);//移除排除的自动化配置
  configurations.removeAll(exclusions);//根据引入的依赖按需导入自动配置
  configurations = filter(configurations, autoConfigurationMetadata);//触发自动化配置
  fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
 }
protected AutoConfigurationEntry getAutoConfigurationEntry(
   AutoConfigurationMetadata autoConfigurationMetadata,
   AnnotationMetadata annotationMetadata) {
        //判断是否开启自动配置
  if (!isEnabled(annotationMetadata)) { 
   return EMPTY_ENTRY;
  }
  AnnotationAttributes attributes = getAttributes(annotationMetadata);
       //获取自动配置文件和配置
  List configurations = getCandidateConfigurations(annotationMetadata,
    attributes);//删除重复项
  configurations = removeDuplicates(configurations);//获取排除的自动化配置
  Set exclusions = getExclusions(annotationMetadata, attributes);//检查排除的自动化配置
  checkExcludedClasses(configurations, exclusions);//移除排除的自动化配置
  configurations.removeAll(exclusions);//根据引入的依赖按需导入自动配置
  configurations = filter(configurations, autoConfigurationMetadata);//触发自动化配置
  fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
 }

filter方法会过滤我们的自动化配置类 ,规则是根据我们配置类上的  @Conditiona系列注解

springboot 写java自动化接口 springboot自动化配置原理_springboot自动配置原理_10