自动配置原理
# SpringBoot 自动配置原理
简单的说,自动配置就是会根据在类路径中的 jar、类自动配置 Bean。Spring Boot 将所有的功能场景都抽取出来,做成一个个的 starter(启动器),只需要在项目里面引入这些 starter,相关场景的所有依赖都会导入进来。
- 自动配置就是基于三个重要的注解实现的(实际就是 @SpringBootApplication 注解)
// @SpringBootConfiguration:我们点进去以后可以发现底层是Configuration注解,其实就是支持JavaConfig的方式来进行配置(使用Configuration配置类等同于XML文件)
// @EnableAutoConfiguration:这个注解用来开启自动配置,是自动配置实现的核心注解
// @ComponentScan:这个注解,就是扫描注解,默认是扫描当前类下的package。将@Controller/@Service/@Component/@Repository等注解加载到IOC容器中
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- @EnableAutoConfiguration 源码
// @AutoConfigurationPackage:自动配置包
// @Import:给IOC容器导入组件
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
1
2
3
4
5
6
2
3
4
5
6
- @AutoConfigurationPackage 源码
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName())
}
// 很容易可以看到,它的作用就是将主配置类(@SpringBootApplication)的所在包及其子包里边的组件扫描到Spring容器中
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- @Import(AutoConfigurationImportSelector.class) 源码
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
// 可以得到了很多配置信息
protected AutoConfigurationEntry getAutoConfigurationEntry(...) {
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 配置信息从这里来
protected List<String> getCandidateConfigurations(...) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(...);
// 配置加载的位置
public static List<String> loadFactoryNames(...) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader)...;
}
private static Map<String, List<String>> loadSpringFactories(...) {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
result.add(factoryClassName, factoryName.trim());
// 这个方法也就是自动配置的核心实现了,主要是三点内容:
// FACTORIES_RESOURCE_LOCATION的值是META-INF/spring.factories
// Spring启动的时候会扫描所有jar路径下的META-INF/spring.factories,将其文件包装成Properties对象
// 从Properties对象获取到key值为EnableAutoConfiguration的数据,然后添加到容器里边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
编辑 (opens new window)
上次更新: 2022/01/08, 16:51:05