SpringBoot自动配置原理分析
引导加载自动配置类
我们从主启动程序入手分析。

| 1 | 
 | 
这里标注了一个@SpringBootApplication注解,我们点击查看源码。

这个注解除了元注解,标注了三个其他的注解。
| 1 | 
 | 
@SpringBootConfiguration
我们首先来分析一下@SpringBootConfiguration注解,查看源码

| 1 | //标志当前是一个配置类 | 
这个类除了元注解就只有@Configuration,所以它的作用也就是标志当前是一个配置类。也就是说我们的主启动程序,也是一个配置类,不过是SpringBoot的一个核心配置类。
@ComponentScan
| 1 | //SpringBoot配置类 | 
接着我们在来看一下@ComponentScan:主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中。
不过这里指定了那些类型和类不扫描,也就是过滤掉。
| 1 | //SpringBoot配置类 | 
@EnableAutoConfiguration
接下来只剩下@EnableAutoConfiguration注解了。这个就是自动配置的核心注解。我们查看源码

| 1 | 
 | 
发现有两个注解@AutoConfigurationPackage 和@Import。
@AutoConfigurationPackage
查看@AutoConfigurationPackage源码。

| 1 | //导入AutoConfigurationPackages.Registrar对象 | 
发现该类通过@Import导入了AutoConfigurationPackages.Registrar组件。我们继续点进去查看源码

| 1 | static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { | 
发现该类只有两个方法registerBeanDefinitions,determineImports.我们在第一个方法中打一个断点,debug查看。

AnnotationMetadata的信息,来自标注@SpringBootApplication(合成注解)的主启动类上。

接着通过AnnotationMetadata或者注解标注类所在的包信息转换成一个数组。然后register注册到IOC容器中。
也就是说@AutoConfigurationPackage注解通过利用Registrar导入注册主程序所在包下所有添加@Component,@Controller….的类到IOC容器中。
这也就就解释了为啥我们在主程序包下或者子包编写配置类,Cotroller…能被自动扫描注册到容器中。
@Import
| 1 | //导入注册主程序包下的组件 | 
我们在来看看@Import(AutoConfigurationImportSelector.class),@Import注解的作用很简单,就是导入注册一个组件到容器中。所以关键是AutoConfigurationImportSelector.class

| 1 | 
 | 
可以看出这里的核心是getAutoConfigurationEntry(annotationMetadata);方法


List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);获取到的configurations的size是130。

这130个组件是要导入到容器中的,它是哪里获取的呢??我们继续查看getCandidateConfigurations

| 1 | List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), | 
我们继续查看loadFactoryNames方法

我们继续查看loadSpringFactories方法

打个断点,debug执行。

我们可以得知它是加载FACTORIES_RESOURCE_LOCATION这个属性, 默认扫描我们当前系统里面所有META-INF/spring.factories位置文件加载组件的。
而自动配置最核心的也就是spring-boot-autoconfigure-2.4.1.jar。我们点开该jar包发现META-INF/spring.factories文件查看。


151-22+1=130正好是我们先前看到的加载的组件个数130个。文件里面写死了spring-boot一启动就要给容器中加载的所有配置类。
按需开启自动配置项
虽然我们130个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration都是都按照条件装配规则@Conditional,最终会按需配置。
例如我们查看文件中的RabbitAutoConfiguration类

@ConditionalOnClass({ RabbitTemplate.class, Channel.class })不存在RabbitTemplate,Channel类所以以下配置都不生效。
用户自定义优先
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先。例如WebMvcAutoConfiguration

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)当容器中没有WebMvcConfigurationSupport类型的组件时配置才生效。
总结
- SpringBoot会扫描所有 - META-INF/spring.factories位置文件加载组件。而自动配置最核心的也就是- spring-boot-autoconfigure-2.4.1.jar。所以加载的是- spring-boot-autoconfigure-2.4.1.jar下- META-INF/spring.factories文件中写好的自动配置类(xxxxxAutoConfiguration)。
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定 
- 生效的配置类就会给容器中装配很多组件 
- 只要容器中有这些组件,相当于这些功能就有了 
定制化配置
- 用户直接自己@Bean替换底层的组件 
- 用户去看这个组件是获取的配置文件什么值就去修改。(配置文件配置) 
spring-boot-autoconfigure.jar —> META-INF/spring.factories —>xxxxxAutoConfiguration —> 组件 —>xxxxProperties里面拿值 —-> application.properties













