002-Spring boot 自动配置相关分析

目录

    • 自动配置
      • 开启自动配置
      • 读取配置
      • 提前过滤

自动配置

开启自动配置

在Spring 启动类上的 @SpringBootApplication 中有 @EnableAutoConfiguration

读取配置

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

也就是导入了 AutoConfigurationImportSelector
我们在 Spring 时代知道这个类会返回配置类的全类名
也就是在 selectImports 方法中返回了自动配置的相关类的全类名的集合
Spring boot 自动装配的配置类有144个
如果一个一个写,那代码就太长了
所以Spring 就把这些配置类都配置在一个文件中

getAutoConfigurationEntry(annotationMetadata)//读取 @EnableAutoConfiguration 的配置信息
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//读取所有的 META-INF/spring.factories 文件中配置的配置类
//读取所有的 @AutoConfiguration 注解的配置类
//这里会把 classLoader里所有的META-INF/spring.factories文件都读出来汇总
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//有序去重 这一步很好玩 平时也可以用 
//new ArrayList<>(new LinkedHashSet<>(list));
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);

META-INF/spring.factories 文件示例:
002-Spring boot 自动配置相关分析_第1张图片

//文件内容 接口 = 类名列表,多个用“,”隔开

文件解析方法 loadSpringFactories():

//读取classLoader中所有的文件
Map<String, List<String>> result = new HashMap<>();
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
	URL url = urls.nextElement();
	//读取并创建资源
	UrlResource resource = new UrlResource(url);
	//解析成 properties 其实就是个 Map
	Properties properties = PropertiesLoaderUtils.loadProperties(resource);
	for (Map.Entry<?, ?> entry : properties.entrySet()) {
		String factoryTypeName = ((String) entry.getKey()).trim();
		// 按 ‘,’ 分割
		String[] factoryImplementationNames =
				StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
		for (String factoryImplementationName : factoryImplementationNames) {
			//这个就是常用的 map的value是list
			result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
					.add(factoryImplementationName.trim());
		}
	}
}
return result;

提前过滤

getConfigurationClassFilter().filter(configurations):

getConfigurationClassFilter():
//读取到三个
//OnBeanCondition
//OnClassCondition
//OnWebApplicationCondition
filters = SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
for (AutoConfigurationImportFilter filter : filters) {
	invokeAwareMethods(filter);
}
//这里再创建 ConfigurationClassFilter 的时候就读取了预处理的配置文件
//META-INF/spring-autoconfigure-metadata.properties
//这个配置类里边已经配好类名和提前过滤配置的内容
return this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);

//根据配置类中的内容提前过滤一下
//OnBeanCondition :没有配置类型的Bean定义就别解析了
//OnClassCondition :没有配置的类文件就别解析了
//OnWebApplicationCondition :不是配置的上下文类型就别解析了
//这样一来就快速的过滤掉一些肯定不能创建的配置类
ConfigurationClassFilter.filter(configurations):

META-INF/spring-autoconfigure-metadata.properties 文件内容示例:
002-Spring boot 自动配置相关分析_第2张图片

你可能感兴趣的:(spring,boot,spring,boot,后端,java)