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类为例,理解自动装配。