自动配置源码解析:
- 项目启动
- 加载所有jar包下 META-INF/spring.factories 文件, 保存在map中,包含了所有的自动配置类 ctrl+n搜索类 ctrl+F12展示所有方法
//spring工厂加载器
public final class SpringFactoriesLoader {
//SpringFactoriesLoader类中的常量FACTORIES_RESOURCE_LOCATION定义了读取文件路径
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
//加载所有jar包下 META-INF/spring.factories 文件,保存在map中
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//classLoader: 一个类加载器
//三元表达式对classLoader进行滤空
Enumeration<URL> urls = (classLoader != null ?
//不为空,加载需要的资源文件,前面常量定义的路径下的文件
classLoader.getResources(FACTORIES_RESOURCE_LOCATION):
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
//在所有jar包下寻找spring.factories文件
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
//通过刚刚找到的spring.factories文件路径解析文件,将结果存入result
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
//将找到的自动配置类缓存进catch map
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
}
项目中所有的jar包
找到一个spring.factories文件
将所有spring.factories的配置进行合并,作为键值对,存入map,我们比较关注"org.springframework.boot.autoconfigure.EnableAutoConfiguration=
"里的内容,这个key下的类都是自动配置类,org.springframework.boot.autoconfigure是springboot自动配置最核心的包
result就是最后生成的那个map(注意,这里一共有130个自动配置类,但不是每一个都需要自动配置)
只有满足条件的自动配置类才会被自动配置
-
获取候选配置类,根据条件过滤掉不满足条件的配置类
AutoConfiguration自动导入;Import导入;Selector过滤;
调用 AutoConfigurationImportSelector类的getAutoConfigurationEntry()方法
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取候选配置,也就是刚刚缓存的130个自动配置(调用过程见图)
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//获取到自动配置类
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//"filter",过滤掉不需要的自动配置类
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations()调用SpringFactoriesLoader.loadFactoryNames()
loadFactoryNames()调用loadSpringFactories()
loadSpringFactories()刚刚已经执行过了,这里获取缓存进去的数据并返回
获取到自动配置类
过滤之后留下的自动配置类
类实现自动配置步骤
- 标注当前类是配置类
- 条件:导入了相关依赖 -> @ConditionalOnClass
- ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean,也就是有没有导入对应的jar包
- ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
- ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
- 读取配置 -> @EnableConfigurationProperties -> 配置类加载配置
- 创建bean对象加入到IOC容器 @Bean
自动配置三要素
- 哪些类是用于实现自动配置
- META-INF/spring.factories文件中自动配置化的类(org.springframework.boot.autoconfigure.EnableAutoConfiguration=\下的类)
- 哪些自动配置类会进行自动配置
- 满足了@conditional条件的自动配置类
- 什么时候开启的自动配置功能
- 自动配置不是默认开启的,需要添加一个注解 @EnableAutoConfiguration
自动装配
启动类上有一个@SpringBootApplication注解
@SpringBootApplication里还有三个注解
- @SpringBootConfiguration : 表示当前类具备配置类的功能
- @EnableAutoConfiguration :开启自动配置
- @AutoConfigurationPackage:自动注册的包(自己工程的自动装配)
- @Import(AutoConfigurationImportSelector.class)(第三方工程的自动装配)
@AutoConfigurationPackage-@Import(AutoConfigurationPackages.Registrar.class)Registrar()
Registrar()
@Import(AutoConfigurationImportSelector.class)加载类中的getAutoConfigurationEntry方法,与前文串联
- @ComponentScan : 组件扫描,加入到IOC容器里
自动配置流程梳理
- 项目启动时,SpringFactoriesLoader类调用loadSpringFactories()方法获取META-INF/spring.factories文件中配置好的的自动配置类
- 启动类的SpringBootApplication注解下的EnableAutoConfiguration注解开启自动配置,EnableAutoConfiguration下的AutoConfigurationPackage加载springboot提供的自动配置类,@Import(AutoConfigurationImportSelector.class)装配第三方的自动配置类
- AutoConfigurationImportSelector类中的getAutoConfigurationEntry()方法去调用loadSpringFactories()方法获取缓存好的自动配置类,并进行过滤,留下需要的自动配置类 4.自动配置类需要满足的条件
- @configuration:配置类
- @conditional:是否自动配置的条件
- @EnableConfigurationProperties:读取配置
- @Bean:放入ioc容器