-目录
SpringBoot自动配置原理
1、@SpringBootConfiguration
2、@ComponentScan
3、@EnableAutoConfiguration(关键)
1)进入@AutoConfigurationPackage
2)进入@Import(AutoConfigurationImportSelector.class)注解
4、按需配置
5、修改默认配置
总结
主类上的注解@SpringBootApplication,ctrl+单击进入可知,相当于重点的几个注解组合
①.@SpringBootConfiguration
②.@EnableAutoConfiguration
③.@ComponentScan(.....)
@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 {
--> 就相当于是标志为这是一个配置类,等价于@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
--> 由该注解中的excludeFilters、@Filter等字眼看出就是指定扫描哪Spring注解的
进入该注解可以看到有@AutoConfigurationPackage和@Import(AutoCo....)两个关键注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
--> 有个关键注解:@Import(AutoConfigurationPackages.Registrar.class),给容器导入组件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {
--> 查看Import导入的配置类Registrar到底注册什么,ctrl单机进入Registrar,大致就是利用Registrar给容器中导入一系列组件(由最后的toArray()可知,将指定的一个包下的所有组件导入进来)
--> 看源码中 selectImports 方法,查看选择导入规则
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
--> 重点分析getAutoConfigurationEntry(annotationMetadata)方法给容器中批量导入一些组件
--> 可以看出先拿到需要导入容器的配置类信息 configurations,然后就是对该配置类信息进行一些了筛选:removeDuplicates(去重)、chekExclude..(排除)、filter...等进行筛选过滤
-->所以重点方法:List
-->可以看到,可获取到127个相关配置类(后面会解释这个127个来源:spring.factories)
--> debug进入getCandidateConfigurations候选配置类方法,分析该方法是如何获取所需要导入容器中的配置类的
-->①.查看loadFactoryNames方法,可以看出由spring的工厂加载器来加载一些东西的,所以再进入loadFactoryNames进行查看
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List 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;
}
-->②.显然还要进而再进入loadFactoryNames方法中的loadSpringFactories查看
public static List loadFactoryNames(Class> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
-->③.最终关键利用工厂加载 Map
-->结论:默认扫描我们当前系统里面所有 META-INF/spring.factories 位置的文件
-->spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
-->文件里写死了spring-boot一启动就给容器中加载的所有配置类(auto Configure:127个)
虽然有127个场景的所有自动配置启动的时候默认全部加载。xxxAutoConfiguration
但是都是由相关注解(@Conditional),安装条件装配规则,最终按需配置的,如图
底层运用了@ConditionalOnBean、@ConditionalOnMissingBean、@Conditional等注解进行条件配置,即默认底层配好所有相应场景地组件的同时,还允许优先使用用户自己配置的
下面看一下底层为我们配好的一些组件
--> 关于springmvc的配置: 即不用像ssm整合那样些一堆配置信息于xml,web.xml中配置dispatcherservlet之类的了,如下图:
-->文件解析器自动配置:联用了@ConditionalOnBean和@ConditionalOnMissingBean两个注解进行规范,即存在文件解析器MutipartResolver才生效(但是也要求用户没有定义相关名为multipartResolver的组件,避免发生冲突)
-->字符编码自动配置:也用到了注解@ConditionalOnMissingBean,只要用户有自己的配置,就以用户的优先
--> 用户直接自己@Bean替换底层的组件
--> 用户去看这个组件是获取的配置文件什么值就去修改即可
如:xxxAutoConfiguration --> 导入许多组件 --> 组件从xxxProperties里面拿值 -->properties跟 application.properties进行了绑定