Spring Boot自动配置原理
POM文件
1.pom文件的作用:导入相关依赖。
2.父项目的作用:版本仲裁。
<!--SpringBoot版本仲裁中心-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
ctrl+鼠标左键点击spring-boot-start-parent会发现这个父项目还依赖另一个父项目,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
在这个父项目下点开spring-boot-dependencies在<properties>
标签下会发现很多版本号,这里我就不一一列举,在这个标签下的依赖大家在导入的时候无需配置版本号,因为系统会自动配置,如果导入的依赖,这里边没有,还是需要配置版本号的。
3.导入的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
由以上代码可见spring-boot-starter是springboot的场景启动器,它帮助我们导入了web模块正常运行所依赖的组件。在开发过程中想用什么功能就导入什么组件。
@SpringBootApplication
相信这个注解大家都不会陌生,它就存在于我们的主配置类中。我们Spring Boot中的自动配置就是和这个注解相关的。
1.首先Ctrl加鼠标左键,点开这个注解大家会看到的以下注解
@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) })
2.Spring基层注解这里就不再做过多的解释,看一下@EnableAutoConfiguration注解点开后会发现有个@Import注解,他的作用是给容器导入组件。导入了什么组件呢?
@Import(AutoConfigurationImportSelector.class)
3.点开AutoConfigurationImportSelector.class这个类在这个类中有一个selectImports()方法,根据方法的返回值我们可以看到这里用了一个getAutoConfigurationEntry方法。
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
4.在getAutoConfigurationEntry()方法中根据返回值我么可以看到以下这段代码,这段代码中,有一个getCandidateConfigurations()方法,他的意思是获取候选配置。
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
5.打开getCandidateConfigurations()方法,可以看到这个方法体中有以下代码。
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
6.点开loadFactoryNames()方法可以找到
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
而FACTORIES_RESOURCE_LOCATION代表的是路径。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
在spring-boot-autoconfigure包下我们通过这个路径找到这个文件,点开后发现有很多的包。
7.那么这个注解真正自动配置的是哪些包呢?回到第五步大家看到 SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());方法中的参数getSpringFactoriesLoaderFactoryClass()打开后可以看到一个方法。
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
返回的是 EnableAutoConfiguration.class.根据这个类名,我们在spring.factories中找到这个类对应的值然后添加到容器中。
总结:@EnableAutoConfiguration的作用是将类路径下META-INF/spring.factories里面配置中所有的EnableAutoConfiguration的值加入到容器中。这就是自动配置的原理