SpringBootApplication-@Import(AutoConfigurationImportSelector.class)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage  //标记自动配置
@Import(AutoConfigurationImportSelector.class)  //使用Import自动导入所有符合自动配置条件的Bean定义并加载到IOC容器
public @interface EnableAutoConfiguration {
...

AutoConfigurationImportSelector

	@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());
	}

AutoConfigurationMetadataLoader

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);
	}

SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第1张图片

SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第2张图片

SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第3张图片
SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第4张图片

PropertiesAutoConfigurationMetadata

	private static class PropertiesAutoConfigurationMetadata implements AutoConfigurationMetadata {

		private final Properties properties;

		PropertiesAutoConfigurationMetadata(Properties properties) {
			this.properties = properties;
		}

SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第5张图片

getAutoConfigurationEntry

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);
	}
  • 2.getCandidateConfigurations
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;
	}
  • loadFactoryNames
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		String factoryTypeName = factoryType.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
	}

loadSpringFactories

加载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);
		}
	}

SpringBootApplication-@Import(AutoConfigurationImportSelector.class)_第6张图片

你可能感兴趣的:(训练,SpringBoot,spring,boot,训练)