@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //标记自动配置
@Import(AutoConfigurationImportSelector.class) //使用Import自动导入所有符合自动配置条件的Bean定义并加载到IOC容器
public @interface EnableAutoConfiguration {
...
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断EnableAutoConfiguration是否开启默认开启true
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//1.加载META-INF/spring-autoconfigure-metadata.properties 文件
//2.从中获取所有符合条件的支付自动装配的类
// protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
//自动配置类全名.条件=条件的值
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
获取AutoConfigurationEntry 见getAutoConfigurationEntry
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
final class AutoConfigurationMetadataLoader {
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
private AutoConfigurationMetadataLoader() {
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
//调用重载方法
return loadMetadata(classLoader, PATH);
}
//protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
try {
//读取spinrg-boot-autoconfigure.jar中的META-INF/spring-autoconfigure-metadata.properties信息生成URL信息
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
: ClassLoader.getSystemResources(path);
Properties properties = new Properties();
/**
* 解析URL放入properties中
*/
while (urls.hasMoreElements()) {
properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
}
return loadMetadata(properties);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
}
}
/**
* new 一个PropertiesAutoConfigurationMetadata对象把Properties包装下
* @param properties
* @return
*/
static AutoConfigurationMetadata loadMetadata(Properties properties) {
return new PropertiesAutoConfigurationMetadata(properties);
}
private static class PropertiesAutoConfigurationMetadata implements AutoConfigurationMetadata {
private final Properties properties;
PropertiesAutoConfigurationMetadata(Properties properties) {
this.properties = properties;
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
//判断EnableAutoConfiguration是否开启默认开启true
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//1.获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//2.获取默认支持的自动配置的列表
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//3.去重
configurations = removeDuplicates(configurations);
//4.排除exclude不需要自动配置的类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//5.验证排除的类
checkExcludedClasses(configurations, exclusions);
//6.移除所有排除的类-不希望自动配置的类
configurations.removeAll(exclusions);
//7.对所有候选的自动配置类进行筛选,
//比如ConditionalOnProperty //当属性存在时
// ConditionalOnClass //当class存在
//ConditionalOnMissingClass 当这个clas不存在时才去配置
//过滤器
configurations = filter(configurations, autoConfigurationMetadata);
//8.将自动配置的类,导入事件监听器,并触发fireAutoConfigurationImportEvents事件
//加载META-INF\spring.factories 中AutoConfigurationImportListener
fireAutoConfigurationImportEvents(configurations, exclusions);
//9创建AutoConfigurationEntry对象
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;
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
加载META-INF/spring.factories中的类
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
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);
}
}