a. 找到其主启动类
@SpringBootApplication
public class SpringBootAutoConfigTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAutoConfigTestApplication.class, args);
}
}
b. 其中@SpringBootApplication表示主启动类,进入此注解,可以看到如下的类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
// 省略代码
}
c. 在此类中,我们主要关注@EnableAutoConfiguration这个注解,当我们点击此注解后可以看到如下类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
d. 其中@AutoConfigurationPackage表示将此包下的所有组件注册到Spring IoC容器中,我们重点关注@Import({AutoConfigurationImportSelector.class})这个注解,我们点击AutoConfigurationImportSelector这个类进去可以看到实现了ImportSelector重写了selectImports方法
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
// 省略部分代码
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
}
e. 其中this.getAutoConfigurationEntry此方法是获得一个自动配置的实体,我们可以点击进入此方法看有什么
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
// 获得@EnableAutoConfiguration中的属性exclude()和excludeName()
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 获得所有自动装配的配置类,是自动装配的核心方法
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 去除重复的配置项
configurations = this.removeDuplicates(configurations);
// 把不需要装配的配置类移除
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
f. 其中this.getAttributes()是获得@EnableAutoConfiguration中的属性exclude()和excludeName();
this.getCandidateConfigurations()方法是获得所有自动装配的配置类,是自动装配的核心方法;
this.removeDuplicates()方法是去除重复的配置项;
this.getExclusions()是根据@EnableAutoConfiguration中的属性exclude()把不需要装配的配置类移除
我们来看getCandidateConfigurations()此方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
g. 在此方法中我们可以看到SpringFactoriesLoader.loadFactoryNames()此静态方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
h. 此方法返回一个集合loadSpringFactories,我们点击此方法
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
i. 在此方法中,我们看到了classLoader.getResources(“META-INF/spring.factories”);这个方法,根据Spring的SPI机制,会扫描classpath下的META-INF/spring.factories文件,我们找到spring-boot-autoconfigure.jar
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,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
...
j. 可以看到有这些自动配置类,然后再回到getAutoConfigurationEntry方法里通过去重,exclude排除等操作得到最终的自动配置类
简单总结如下:
通过@EnableAutoConfiguration里的@Import({AutoConfigurationImportSelector.class})实现配置类的导入
AutoConfigurationImportSelector这个类实现了ImportSelector接口并且重写了selectImports方法来选择性批量配置类
通过SpringFactoriesLoader.loadFactoryNames()此静态方法扫描classpath下的META-INF/spring.factories文件,读取需要实现的自动装配的配置类
通过去重,exclude排除等操作得到最终的自动配置类
以上就是SpringBoot的自动装配原理,有了这些自动装配类,免去了我们手动编写配置文件的工作从而提高开发效率。也为后面SpringCloud出生做了铺垫。