SpringBoot的自动配置
参考视频:每一帧都是干货!15分钟的视频花2小时看
一、配置类(Configuration Class)
广义的配置类:被注解@Component直接或间接修饰的某个类,即我们常说的Spring组件,其中包括了@Configuration类
侠义的配置类:特指被注解@Configuration所修饰的某个类,又称为@Configuration类
二、SpringBoot自动配置实例
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置Redis服务器
spring:
redis:
database:0
host:127.0.0.1
port:6379
password:123456
- 直接使用RedisTemplate或StringRedisTemplate
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
- 提出问题:自动配置
- 我们除了通过maven引入一个starter外,其他什么也没有做,但是呢,SpringBoot就自动完成了Redis的配置,将相关的Bean对象注册到IOC容器中了。那么SpringBoot是如何做到这一点的呢?这就是这篇博客所要说明的问题了。
三、自动配置,一切从注解@SpringBootApplicaiton说起
- @SpringBootApplication注解
- Spring SPI机制与Spring Factories机制
Spring SPI超简单
- 下面我们逐步分析@EnableAutoConfiguration的自动配置
- @SpringBootApplication
- @EnableAutoConfiguration
- @Import(AutoConfigurationImportSelector.class)
- AutoConfigurationImportSelector.class的关键代码selectImports()方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata){
if(!isEnabled(annotationMetadata))
return NO_IMPORTS;
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//SpringBoot自动配置的入口方法
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationErtadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
- selectImports()方法中引用的getAutoConfigurationEntry()
protected AutoConfigurationEntry getAutoConfigurationEntry(
AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata){
//1. 获取annotationMetadata的注解@EnableAutoConfiguration的属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//2. 从资源文件Spring.factories中获取EnableAutoConfiguration对应的所有的类
List<String> configurations = getCandidateConfigurations(
annotationMetadata, attributes);
//3. 通过在注解@EnableAutoConfiguration设置exclude的相关属性,可以排除指定的自动配置类
Set<String> exclusions = getExclusions(anntationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//4. 根据注解@Conditional来判断是否需要排除某些自动配置类
configurations filter = filter(configurations, autoConfigurationMetadata);
//5. 触发AutoConfiguration导入的相关事件
fireAutoCOnfigurationImportEvents(configurations, exclusions);
return new AutofigurationEntry(configurations, exclusions);
}
- getAutoConfigurationEntry()引用的getCandidateConfigurations()
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes){
//通过SpringFactories机制,从配置文件Spring.factories中找出所有的自动配置类
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
EnableAutoConfiguration.class, getBeanClassLoader());
Assert.notEmpty(configurations,"No auto configuration classes found");
return configurations;
}
- getCandidateConfigurations方法,选择META-IF/spring.factories的,EnableAutoConfiguration类
四、@EnableAutoConfiguration自动配置总体流程
五、这里是给我自己提个醒
META-IF/spring.factories是在Maven引入的Jar包中,每一个Jar都有自己META-IF/spring.factories,所以SpringBoot是去每一个Jar包里面寻找META-IF/spring.factories,而不是我的项目中存在META-IF/spring.factories(当然也可以存在,但是我项目的META-IF/spring.factories肯定没有类似以下这些东西)