你真的了解Spring Boot 自动装配的原理么?很多小伙伴就直接开始从主类上的注解@SpringBootApplication 开始点击,然后一直点击到类org.springframework.boot.autoconfigure.AutoConfigurationImportSelector,然后会执行哪里哪里,估计也是人云亦云,有没有想过为啥会要走@SpringBootApplication ?什么时候走?好了,废话不多少,我们来探索真正的自动装配原理。
其实我在之前的文章Alian解读SpringBoot 2.6.0 源码(七):启动流程分析之准备应用上下文 就讲到了很重要的一部分知识,那就是主类资源的加载和注册。希望大家看完我下图标注的,再看下去会比较容易理解。
同样的我在之前的文章Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(中) 就讲到了后置处理器ConfigurationClassPostProcessor 的获取,具体如下图:
认真理解我所说的这两个点后,开始我们的解读,因为这些我在之前的文章就已经解读很细了,这里只是引用而已,具体的还是需要大家自己认真调试到这里,具体的代码如下:
final class PostProcessorRegistrationDelegate {
private PostProcessorRegistrationDelegate() {
}
// 此方法最重要的是要确保注册和调用按照指定的顺序,比如PriorityOrdered和Ordered
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 定义Set集合processedBeans
Set<String> processedBeans = new HashSet<>();
// beanFactory 就是DefaultListableBeanFactory,它实现了接口BeanDefinitionRegistry
// 故此处是BeanDefinitionRegistry的实例
if (beanFactory instanceof BeanDefinitionRegistry) {
// 转为BeanDefinitionRegistry
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 定义BeanFactoryPostProcessor列表
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 定义BeanDefinitionRegistryPostProcessor列表,属于BeanDefinitionRegistryPostProcessor的实例的
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 从上一步我们知道beanFactoryPostProcessors有两个:
// CachingMetadataReaderFactoryPostProcessor 和 ConfigurationWarningsPostProcessor
// 开始遍历后置处理器beanFactoryPostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 都实现了BeanDefinitionRegistryPostProcessor接口
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// 转为BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
// 调用后置处理器的postProcessBeanDefinitionRegistry
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 加入到BeanDefinitionRegistryPostProcessor列表
registryProcessors.add(registryProcessor);
} else {
// 加入到BeanFactoryPostProcessor列表
regularPostProcessors.add(postProcessor);
}
}
// 定义当前调用的BeanDefinitionRegistryPostProcessor列表
// 同样不要在这里初始化FactoryBeans:需要确保所有常规Bean未初始化以使beanFactory后处理器应用于它们
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,调用实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取对应的后处理器,添加到当前调用的BeanDefinitionRegistryPostProcessor列表
currentRegistryProcessors.add(beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class));
// 添加到Set集合processedBeans
processedBeans.add(ppName);
}
}
// 排序,此处得到的就是ConfigurationClassPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 把当前实现了PriorityOrdered接口BeanDefinitionRegistryPostProcessor列表都加入到BeanDefinitionRegistryPostProcessor列表
registryProcessors.addAll(currentRegistryProcessors);
// 循环调用postProcessBeanDefinitionRegistry()方法(实现了PriorityOrdered接口)
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 后续的代码省略,只需要到上面这一行即可
// 后续的代码省略
// 后续的代码省略
} else {
// 后续的代码省略
}
}
//上面就是调用本类的这个方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
//核心调用是下面这句
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
}
因为postProcessors得到就只有一个对象,那就是ConfigurationClassPostProcessor ,接下里我们就去看看是如何一步步调用的。
具体的类路径:org.springframework.context.annotation.ConfigurationClassPostProcessor
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware{
//从注册表中的配置类派生进一步的bean定义。
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
//处理配置bean的定义
processConfigBeanDefinitions(registry);
}
//基于配置类的注册表构建并验证配置模型。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//定义列表configCandidates用于存放配置类
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取注册表中定义的所有bean的名称,如果未定义,则为空数组
//本版本为springboot2.6.0,一共有7个(当然如果你自己也定义了配置类或者增加了其他的依赖会更多)
String[] candidateNames = registry.getBeanDefinitionNames();
//遍历bean的名称列表
for (String beanName : candidateNames) {
//通过名称后去bean的定义
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判断是否符合配置类的资格,比如包含@Configuration注解(里面会扫描类的注解及父注解)
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//是配置类则加入配置类候选列表
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果未找到@Configuration类,则立即返回
if (configCandidates.isEmpty()) {
return;
}
// 按先前确定的@Order值排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
//检测通过封闭应用程序上下文提供的任何自定义bean名称生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
//本文environment是ApplicationServletEnvironment
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//创建一个新的ConfigurationClassParser实例,该实例将用于填充配置类集。
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//list转为set
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
//初始化已经解析的配置集合
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析每个@Configuration类,这个是核心
parser.parse(candidates);
// 校验配置类
parser.validate();
//此后的代码省略
//此后的代码省略
//此后的代码省略
}
while (!candidates.isEmpty());
//此后的代码省略
//此后的代码省略
//此后的代码省略
}
}
而得到的candidateNames就是如下列表:
实际上倒数第二个就是我们的主类
package com.alian.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
具体的类路径:org.springframework.context.annotation.ConfigurationClassParser
class ConfigurationClassParser {
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
//我们的注解是带注解@SpringBootApplication的bean
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
} else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//核心处理
this.deferredImportSelectorHandler.process();
}
}
这里有两个重要步骤
同样的具体的类路径:org.springframework.context.annotation.ConfigurationClassParser,我们先看看主类的解析。
class ConfigurationClassParser {
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
//根据@Conditional 注解确定是否应跳过项
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//是否已解析过
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
//明显我们的主类还未解析existingClass 为null
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
} else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 递归处理配置类及其超类层次结构
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
//核心解析过程
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
//放到已解析的map中
this.configurationClasses.put(configClass, configClass);
}
}
我继续看下doProcessConfigurationClass方法,同样的具体的类路径还是:org.springframework.context.annotation.ConfigurationClassParser
//通过读取源类(我们的主类)中的注释、成员和方法,应用处理并构建完整的ConfigurationClass
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//判断是否有@Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 如果有递归处理任何成员(嵌套)类
processMemberClasses(configClass, sourceClass, filter);
}
// 处理带@PropertySource注解的类(主类中没有)
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理带@ComponentScan注解的类
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理带@Import 注解的类
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 处理带@ImportResource 注解的类
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理单个@Bean方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口上的默认方法
processInterfaces(configClass, sourceClass);
// 如果有父类则处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 没有父类->处理完成
return null;
}
我继续看下DeferredImportSelectorHandler的process()方法,它是:org.springframework.context.annotation.ConfigurationClassParser的内部类
class ConfigurationClassParser {
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
private class DeferredImportSelectorHandler {
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
//遍历列表并调用register方法获取ImportGroup,此处是得到AutoConfigurationGroup.class
deferredImports.forEach(handler::register);
//处理GroupImports
handler.processGroupImports();
}
}finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
/**
* Environment property that can be used to override when auto-configuration is
* enabled.
*/
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
private class DeferredImportSelectorGroupingHandler {
private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();
private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
public void register(DeferredImportSelectorHolder deferredImport) {
//deferredImport.getImportSelector()获得AutoConfigurationImportSelector
//然后调用getImportGroup()得到AutoConfigurationGroup.class
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
//创建DeferredImportSelectorGrouping的实例
//分组选择器和延迟分组选择器组的映射
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
//延迟导入的配置类的元数据和延迟导入的配置类的映射
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
//这里的关键就是grouping.getImports()方法
grouping.getImports().forEach(entry -> {
//中间代码省略
//中间代码省略
//中间代码省略
});
}
}
}
注册时:
执行时:
class ConfigurationClassParser {
private static class DeferredImportSelectorGrouping {
public Iterable<Group.Entry> getImports() {
//遍历延迟导入选择器处理器,它有两个关键属性
//一个是configurationClass:我们的主类com.alian.springboot.SpringbootApplication
//一个是importSelector:org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
//这个地方才是自动装配的入口
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
//返回每个导入及其关联的配置类
return this.group.selectImports();
}
}
}
关键方法 process 第一个参数就是元数据 ,这里的值是:com.alian.springboot.SpringbootApplication ;第二个参数是延迟导入选择器 ,这里的值是:AutoConfigurationImportSelector ,然后调用AutoConfigurationImportSelector的 process方法,这样才是真的进入到这个类的执行。
AutoConfigurationImportSelector.java
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
private static class AutoConfigurationGroup
implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
//获取自动配置实体
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
//加入到自动配置列表,每个选择器对应响应的实体
this.autoConfigurationEntries.add(autoConfigurationEntry);
//遍历列表
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
//把导入类名和元数据映射起来
//这里的类名就是自动配置的类名
//元数据就是我们的主类元数据
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
}
//返回自动配置ImportSelector。基于导入@Configuration类的AnnotationMetadata的自动配置实体。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//获取元数据上的注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//根据元数据和注解属性获取候选配置类(核心方法)
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//移除重复配置类
configurations = removeDuplicates(configurations);
//获得注解中被exclude和excludeName排除的类的集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//检查被排除类(不符合条件则抛出异常,比如是否可实例化、是否被自动注册配置所使用)
checkExcludedClasses(configurations, exclusions);
//在候选配置类中去除掉被排除的类
configurations.removeAll(exclusions);
//过滤配置类
configurations = getConfigurationClassFilter().filter(configurations);
//将配置类和排除类通过事件传入到监听器中
fireAutoConfigurationImportEvents(configurations, exclusions);
//返回符合条件的自动配置类的全限定名数组
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//Spring工厂加载机制,这个我讲过了
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;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
}
process方法主要还是调用核心的方法 getAutoConfigurationEntry,我们说下它大概的流程:
此方法所在类的具体路径:org.springframework.core.io.support.SpringFactoriesLoader
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
// 此处的类加载器是appClassLoader
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
//如果为空则再次获取
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
// 类的全限定名称(即解析properties文件中需要的key值)
String factoryTypeName = factoryType.getName();
// 根据类加载器,加载classpath下/META-INF/spring.factories下所有的类名称列表
// 从结果Map>中,根据指定类型获取所有实现类名称的集合List
// 核心
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
此方法所在类的具体路径:org.springframework.core.io.support.SpringFactoriesLoader
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
// 根据类加载器去缓存中获取加载好的结果集
//因为SpringApplication实例化时就加载过一次了,这里就是从缓存中获取到值了
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
//结果不为空,则返回
return result;
}
//已从缓存获取到结果,后面代码省略
//已从缓存获取到结果,后面代码省略
//已从缓存获取到结果,后面代码省略
}
因为SpringApplication实例化时就加载过一次了,这里就是从缓存中获取到值了,讲到这里我想就不用我多讲了,结合我之前的文章Alian解读SpringBoot 2.6.0 源码(一):SpringApplication对象创建(Spring工厂加载机制)就完全清楚了,我这篇文章里把超级详细的加载过程都讲解了,这里就不在占用篇幅了。只不过本文中就是加载实现了org.springframework.boot.autoconfigure.EnableAutoConfiguration 的类而已。也就是从META-INF/spring.factories文件中获取EnableAutoConfiguration的实现类,我这个版本是133个,最终符合条件的配置类就是24个:
这个时候就得到了需要进行自动装配的类了,章节2.3.4后面有个调用(this.group.selectImports())返回每个导入及其关联的配置类,它调用的就是AutoConfigurationGroup 的selectImports()方法,后续遍历结果,一个个执行导入的配置类,完成最后的自动配置操作。
从这里看到,我们只需要把要加载的类配置到META-INF/Spring.factories 文件里,SpringBoot 会自动去加载它,很方便我们自己或者是第三方去扩展,我们也可以实现自己 starter,我之前写Alian 的 Spring Cloud就写了很多的starter。