@SpringBootApplication》@EnableAutoConfiguration》@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@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());
}
/**
具体用来加载自动配置类的方法
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
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 = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
// 返回最终需要的配置
//@Param1:用来存储需要的配置项
//@Param2:用来存储排除的配置项
return new AutoConfigurationEntry(configurations, exclusions);
}
}
/**
获取候选配置类【最重要!!!!!】
*/
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;
}
/**
getCandidateConfigurations候选配置类 辅助方法
*/
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
// 返回的是EnableAutoConfiguration字节码对象
return EnableAutoConfiguration.class;
}
/**
getCandidateConfigurations候选配置类 辅助方法
*/
protected ClassLoader getBeanClassLoader() {
// 是一个类加载器
return this.beanClassLoader;
}
/**
getAutoConfigurationEntry具体用来加载自动配置类的方法 辅助方法
*/
protected static class AutoConfigurationEntry {
// 用来存储需要的配置项
private final List<String> configurations;
// 用来存储排除的配置项
private final Set<String> exclusions;
}
SpringFactoriesLoader.java
//加载配置文件的路径:
//也就是项目启动的时候会去加载所有 META-INF 下的所有的 spring.factories 文件
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
/**
这个方法就是根据刚才的字节码文件和类加载器来找到候选的配置类。
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
//获取的EnableAutoConfiguration.class的全限定名
//org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
/**
通过loadSpringFactories()来获取到所有的配置类
*/
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 缓存加载的配置类
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
// 去资源目录下找
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
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());
}
}
}
// 加载完成放到缓存中
cache.put(classLoader, result);
// 返回加载到的配置类
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
标签:return,springboot,配置,annotationMetadata,自动,result,原理,加载,configurations
From: https://www.cnblogs.com/goodluckxiaotuanzi/p/18339419