「这是我参与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 的源码
- 利用
getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)给容器批量导入一些组件- 调用
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类- 利用工厂加载
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)得到所有的组件- 从
META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件- 当我们没有引入任何扩展
starter时,会加载spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面的META-INF/spring.factories文件里面写死了SpringBoot一启动就要给容器中加载的所有配置类,但是在真正装配的时候会按条件规则(@Conditional)来完成最终配置。
总结
- 主程序所在包下得组件会自动加载,主要是 @AutoConfigurationPackage 注解下得 Register 的作用。
- 项目启动时默认会全部加载,按需配置