自动配置原理
SpringBoot特点
依赖管理
父项目做依赖管理
依赖管理 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> 他的父项目 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.2.RELEASE</version> </parent> 依赖包的版本仲裁 <activemq.version>5.15.13</activemq.version> <antlr2.version>2.7.7</antlr2.version> <appengine-sdk.version>1.9.81</appengine-sdk.version> <artemis.version>2.12.0</artemis.version> <aspectj.version>1.9.6</aspectj.version> <assertj.version>3.16.1</assertj.version> <atomikos.version>4.0.6</atomikos.version> <awaitility.version>4.0.3</awaitility.version> <bitronix.version>2.1.4</bitronix.version> <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version> <byte-buddy.version>1.10.13</byte-buddy.version> <caffeine.version>2.8.5</caffeine.version> <cassandra-driver.version>4.6.1</cassandra-driver.version> <classmate.version>1.5.1</classmate.version> <commons-codec.version>1.14</commons-codec.version> ......
加入场景启动器
***-spring-boot-starter 为场景启动器 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
@ConfigurationProperties
配置文件的属性和实体类进行关联,只要容器中的组件才有这个功能
@ConfigurationProperties(prefix = "mycar") public class Car { private String brand; private Integer price; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } @Override public String toString() { return "Car{" + "brand='" + brand + '\'' + ", price=" + price + '}'; } }
@EnableConfigurationProperties + @ConfigurationProperties或者**@Component + @ConfigurationProperties**
@EnableConfigurationProperties(Car.class) //1、开启Car配置绑定功能 //2、把这个Car这个组件自动注册到容器中 public class MyConfig { }
自动配置原理入门
@SpringBootApplication:
@SpringBootConfiguration
@EnableAutoConfiguration
@SpringBootConfiguration:可以发现它本质就是一个Configuration注解,一个spring的配置类
@Configuration
public @interface SpringBootConfiguration {}
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage
自动配置包,给容器导入组件
@Import(AutoConfigurationPackages.Registrar.class)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
获取到包名的位置,将指定的一个包下的所有组件导入进来。
@Import(AutoConfigurationImportSelector.class)
// 给容器中批量导入组件
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry =
// 核心方法 利用这个方法给容器中批量导入一些组件
getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 这句是核心获取候选配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
默认将235个组件导入到容器中
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//这句是核心 读取配置
List<String> 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;
}
通过SpringFactoriesLoader.loadFactoryNames
读取自动配置参数
进去loadSpringFactories
函数之后显示去 缓存里面查看有没有配置参数
关键看下面这个map的项 org.springframework.boot.autoconfigure.EnableAutoConfiguration
,这个对面的就是自动的类。
那如果没有缓存呢?紧接着执行这句话去读取META-INF/spring.factories
.
classLoader.getResources()
去读classsLoader
这个类加载器路径下的的META-INF/spring.factories
的配置文件。
至于这个classLoader时那个类 我们回溯一下。
进入EnableAutoConfiguration.class
去看一下!
最终发现这个类在这
而自动配置文件就在他的类路径下面

查看result
的值可以发现和MybatisAutoConfiguration
里面的META-INF\spring.factories
里面的配置一模一样。
210322222712.png" alt=“image-20210322222708373” style=“zoom:50%;” />
[外链图片转存中…(img-NV5cwFyS-1617804176476)]
[外链图片转存中…(img-yrgYndWg-1617804176477)]
查看result
的值可以发现和MybatisAutoConfiguration
里面的META-INF\spring.factories
里面的配置一模一样。
至此就可以大致知道spingboot是如何做到自动配置的,基本就是和spring.factories这个文件有关。