1 springboot启动的时候加载主配置类,开启自动配置功能。

  而自动配置功能的开启主要依靠@SpringBootApplication ===》@EnableAutoConfiguration注解来实现的。

2 @EnableAutoConfiguration开启自动配置。  

@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration

@EnableAutoConfiguration主要通过@Import(EnableAutoConfigurationImportSelector.class)选择器向容器中注入了一些组件。            导入了那些组件呢?

总结:通过导入EnableAutoConfigurationImportSelector这个类,把类路径下的jar包的META-INF/spring.factories文件中配置EnableAutoConfiguration属下的所有组件注入到容器中。

源码解读:

public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
      //xxxx这都不重要
}

EnableAutoConfigurationImportSelector类的父类AutoConfigurationImportSelector是一个ImportSelector(选择器),通过以前的spring注解的知识可以得知,选择器的作用就是将选择器返回的组组件注入到容器。AutoConfigurationImportSelector通过重写selectImports()方法,将该方法的返回值注入到容器中。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		try {
			AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
					.loadMetadata(this.beanClassLoader);
			AnnotationAttributes attributes = getAttributes(annotationMetadata);
			/**
			*通过getCandidateConfigurations()方法添加的list的内容
			*getCandidateConfigurations():获取候选的配置
			*/
			List<String> configurations = getCandidateConfigurations(annotationMetadata,
					attributes);

			/****/

			//最终返回的是一个List<String>的configurations,那么这个list里面加入了什么内容呢?
			return configurations.toArray(new String[configurations.size()]);
		}
		catch (IOException ex) {
			throw new IllegalStateException(ex);
		}
	}

getCandidateConfigurations():获取导入组件的名称的list集合。

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

SpringFactoriesLoader.loadFactoryNames()

方法会去扫描jar包类路径下的 “META-INF/spring.factories”所有文件。把扫描到的文件最终转换成Properties文件然后从每个Properties文件中获取EnableAutoConfiguration.class对应的值,组成list集合返回给容器。

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
	String factoryClassName = factoryClass.getName();
	try {
		//会去获取所有jar包的META-INF/spring.factories这个文件的URL
		Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
				ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
		List<String> result = new ArrayList<String>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			//然后将每个URL都包装成Properties文件
			Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
			//去这个文件中取得到factoryClassName=EnableAutoConfiguration.class属性对应的值
			String factoryClassNames = properties.getProperty(factoryClassName);
			//将得到的属性值返回.
			result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
		}
		return result;
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
				"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
}

最终加入的组件:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
****************等等
每一个XxxAutoConfiguration类,最终都会被注册到容器中。

PS:@EnableAutoConfiguration注解的最终作用就是通过添加该注解,把类路径下所有jar包的META-INF/spring.factories”路径下spring.factories文件里面的EnableAutoConfiguration属性节点所对应的值返回,返回值里面包含的一个个的组件,最终会这些组件注册到容器中去。

PS:所以,所谓的开启自动配置其实就是注册@EnableAutoConfiguration==》@Import==》导入一个ImportSelector的返回值。

3 只有将上面的组件。添加到容器中后,自动配置才能开始。

4 XxxAutoConfiguration这些类都是自动装配类。每一个自动配置类进行自动配置。

5  以HttpEncodingAutoConfiguration类为例,理解自动装配。