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