SpringBoot | 自动配置原理

287 阅读2分钟

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」。

前言

在使用 SpringBoot 的时候我们知道,它会自动加载配置一些我们常用场景下的 bean,包括我们只要引入starter 对应的 bean 在项目启动的时候会自动注入到 Spring 容器中,但是这之间的原理往往容易被忽视掉了。

@SpringBootApplication

@SpringBootApplication 可以说是一个 SpringBoot 项目的标志注解,类上加上该注解,表明该类为主程序类或者主配置类。

  • 它是一个组合注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

查看源码,是由 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan 三个注解组合而成

1. @SpringBootConfiguration

查看其源码,这个注解本质其实就是 @Configuration,带表当前类是一个配置类。

2. @ComponentScan

组件扫描类,指定扫描哪些 Spring 注解

3. @EnableAutoConfiguration

注解的翻译为:开启自动配置。这个其实就是 SpringBoot 自动配置的核心注解了,看一下源码。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

这也是一个组合注解,@AutoConfigurationPackage@Import

1. @AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

自动配置包,发现它的本质也是使用 @Import 注解导入一些组件。 这里和我们之前使用的,指定具体类型导入一个组件不一样,它是利用 Register 给容器中导入一系列的组件,而这个 Register 的作用则是,检测这个注解所在的类的包下,所有的组件。而这个注解就加在主配置类上,这就是为什么主配置类所在包下的配置类不用添加组件扫描,默认会加载的原因。

2. @Import(AutoConfigurationImportSelector.class)

查看 AutoConfigurationImportSelector 的源码

  1. 利用 getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) 给容器批量导入一些组件
  2. 调用 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes) 获取到所有需要导入到容器中的配置类
  3. 利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) 得到所有的组件
  4. META-INF/spring.factories 位置来加载一个文件。 默认扫描我们当前系统里面所有 META-INF/spring.factories 位置的文件
  5. 当我们没有引入任何扩展 starter 时,会加载 spring-boot-autoconfigure-2.3.4.RELEASE.jar 包里面的 META-INF/spring.factories 文件里面写死了 SpringBoot 一启动就要给容器中加载的所有配置类,但是在真正装配的时候会按条件规则(@Conditional)来完成最终配置。

总结

  1. 主程序所在包下得组件会自动加载,主要是 @AutoConfigurationPackage 注解下得 Register 的作用。
  2. 项目启动时默认会全部加载,按需配置