基于Spring Boot 3.1.0 系列文章
- Spring Boot 源码阅读初始化环境搭建
- Spring Boot 框架整体启动流程详解
- Spring Boot 系统初始化器详解
- Spring Boot 监听器详解
- Spring Boot banner详解
- Spring Boot 属性配置解析
- Spring Boot 属性加载原理解析
- Spring Boot 异常报告器解析
- Spring Boot 3.x 自动配置详解
Spring Boot :3.1
Java: 17
前言
Spring Boot 3.x 中的自动配置使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,而不是META-INF/spring.factories
,这个变动其实在2.7的时候已经改变
2.6.9版本文档介绍
2.7.0版本介绍
文档中有创建自己的Starter的详细介绍,《Spring Boot 中文参考指南-创建自己的自动配置》
加载原理
Spring Boot 3.x的自动配置加载入口是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,Spring Boot会读取该文件中的自动配置类,并实例化,我们以该文件为入口。
如果你是新手,并且没有资料可查,可以使用IDE的全局文件搜索功能,搜索关键词,如我搜索
org.springframework.boot.autoconfigure.AutoConfiguration.imports
的结果如下,再通过打断点的方式就能判断加载该文件的入口。
可知,该文件的加载是由AutoConfigurationImportSelector
类进行处理,但AutoConfigurationImportSelector
类又是如何加载的。
通过断点的堆栈可知加载使用到了Spring 框架refresh()
中的invokeBeanFactoryPostProcessors
,其作用是在实例化Bean之前加载额外定义的Bean到上下文中,我们从头开始梳理,能力强的可以掌握方法自行阅读。
堆栈信息
AbstractApplicationContext-invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// 如果beanFactory中是否包含LoadTimeWeaver,如果包含则使用临时ClassLoader进行处理,LoadTimeWeaver是一种类加载器的动态织入技术if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}
该方法的作用是:实例化并调用注册的BeanFactoryPostProcessor
getBeanFactoryPostProcessors()
用来获取所有的BeanFactoryPostProcessor
实例,BeanFactoryPostProcessor
实例通过ApplicationContextInitializer
来加载到上下文中,ApplicationContextInitializer
的加载原理可以通过前面的文章了解《Spring Boot 系统初始化器详解》。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
委托处理BeanFactoryPostProcessor。
PostProcessorRegistrationDelegate-invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();//如果beanFactory 是BeanDefinitionRegistry的实现,先处理BeanDefinitionRegistryPostProcessorsif (beanFactory instanceof BeanDefinitionRegistry registry) {List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {regularPostProcessors.add(postProcessor);}}List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();// 先处理 PriorityOrdered 的 BeanDefinitionRegistryPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);//处理BeanDefinitionRegistryPostProcessorsinvokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// 再处理 Ordered 的 BeanDefinitionRegistryPostProcessorpostProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// 最后处理剩余的 BeanDefinitionRegistryPostProcessor,直到没有新的 BeanDefinitionRegistryPostProcessor 添加为止boolean reiterate = true;while (reiterate) {reiterate = false;postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);reiterate = true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();}// 处理所有 BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// 处理普通的上下文中的BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}//获取所有常规化Bean,但不初始化,保留让后期的post-processors处理String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);//分离实现PriorityOrdered、Ordered和其他的BeanFactoryPostProcessorsList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// 跳过已经处理的}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}//首先处理实现了PriorityOrdered的BeanFactoryPostProcessorssortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);//处理实现了Ordered的BeanFactoryPostProcessorsList<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 最后处理其他的BeanFactoryPostProcessorsList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// 清除缓存beanFactory.clearMetadataCache();}
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
是处理自动配置的关键点
PostProcessorRegistrationDelegate-invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {//循环处理BeanDefinitionRegistryPostProcessor实现for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {//步骤日志记录StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process").tag("postProcessor", postProcessor::toString);postProcessor.postProcessBeanDefinitionRegistry(registry);postProcessBeanDefRegistry.end();}
}
BeanDefinitionRegistryPostProcessor
接口继承了BeanFactoryPostProcessor接口,允许在初始化Bean实例之前修改、添加、删除容器中注册的Bean定义信息
在该示例的SpringBoot-Demo中,只有一个BeanDefinitionRegistryPostProcessor实现,即ConfigurationClassPostProcessor
ConfigurationClassPostProcessor-postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//计算hashcodeint 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);}
ConfigurationClassPostProcessor-processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List<BeanDefinitionHolder> configCandidates = new ArrayList<>();//获取容器中所有的bean定义名称String[] candidateNames = registry.getBeanDefinitionNames();for (String beanName : candidateNames) {// 获取 bean 的定义BeanDefinition beanDef = registry.getBeanDefinition(beanName);// 检查该 bean 是否已经被处理成配置类if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}// 检查该 bean 是否是配置类候选者else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// 如果没有需要处理的配置类,则直接返回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) {sbr = _sbr;if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {this.componentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}if (this.environment == null) {this.environment = new StandardEnvironment();}// 解析每个 @Configuration 类ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());do {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");//解析parser.parse(candidates);//验证parser.validate();Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());//去除已经解析的类configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
// 检查新的 BeanDefinition 是否包含新的配置类候选者candidates.clear();if (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames();Set<String> oldCandidateNames = Set.of(candidateNames);Set<String> alreadyParsedClasses = new HashSet<>();for (ConfigurationClass configurationClass : alreadyParsed) {alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}for (String candidateName : newCandidateNames) {if (!oldCandidateNames.contains(candidateName)) {BeanDefinition bd = registry.getBeanDefinition(candidateName);if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName));}}}candidateNames = newCandidateNames;}}while (!candidates.isEmpty());// 注册 ImportRegistry 为一个 bean,以支持 @ImportAware ConfigurationClassif (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());}// 存储 PropertySourceDescriptors,便于在AOT中使用this.propertySourceDescriptors = parser.getPropertySourceDescriptors();if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {// 清除缓存,防止由于缓存无法更新导致的出错问题cachingMetadataReaderFactory.clearCache();}}
此处代码很长,对于配置类的解析,在parser.parse(candidates)
中完成。
parser
变量的实例为:ConfigurationClassParser
ConfigurationClassParser-parse
public void parse(Set<BeanDefinitionHolder> configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();try {// 如果 BeanDefinition 是一个 AnnotatedBeanDefinition,则需要解析该 BeanDefinition 中的注解信息if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {parse(annotatedBeanDef.getMetadata(), holder.getBeanName());}// 如果 BeanDefinition 不是 AnnotatedBeanDefinition,并且具有 beanClass 属性,则解析该 beanClass 中的注解信息else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {parse(abstractBeanDef.getBeanClass(), holder.getBeanName());}else {// 如果 BeanDefinition 没有 beanClass 属性,则解析该 BeanDefinition 中的 beanClassName 所指定的类中的注解信息parse(bd.getBeanClassName(), holder.getBeanName());}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);}}//处理所有的DeferredImportSelector实例this.deferredImportSelectorHandler.process();}
在开始的时候,我们已经知道实际解析自动配置类是AutoConfigurationImportSelector
,AutoConfigurationImportSelector 实现了DeferredImportSelector
接口,而这里正好有deferredImportSelectorHandler
来处理所有的deferredImportSelectorHandler实例。看下DeferredImportSelectorHandler
中的process。
DeferredImportSelectorHandler-process
public void process() {List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;this.deferredImportSelectors = null;try {if (deferredImports != null) {DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);deferredImports.forEach(handler::register);handler.processGroupImports();}}finally {this.deferredImportSelectors = new ArrayList<>();}}
DeferredImportSelectorGroupingHandler
类是在 Spring Boot 中处理 DeferredImportSelector 接口的辅助类,主要用于按照分组将DeferredImportSelector分组进行处理。
此处,我们要关注handler.processGroupImports()
,调用到DeferredImportSelectorGroupingHandler
类的processGroupImports方法。
DeferredImportSelectorGroupingHandler-processGroupImports
public void processGroupImports() {//遍历所有分组for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {//获取候选过滤器Predicate<String> exclusionFilter = grouping.getCandidateFilter();//遍历分组中的每个元素grouping.getImports().forEach(entry -> {ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());try {//处理当前元素processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),exclusionFilter, false);}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configurationClass.getMetadata().getClassName() + "]", ex);}});}}
这里首先要关注grouping.getImports()
,在这里对自动配置类进行了加载
DeferredImportSelectorGrouping-getImports
public Iterable<Group.Entry> getImports() {for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
//处理每个分组的DeferredImportSelectorHolderthis.group.process(deferredImport.getConfigurationClass().getMetadata(),deferredImport.getImportSelector());}//返回需要导入的类return this.group.selectImports();
}
this.group.process
中进入到AutoConfigurationImportSelector
的内部类AutoConfigurationGroup
中
AutoConfigurationImportSelector-AutoConfigurationGroup-process
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()));//转为为AutoConfigurationImportSelector,获取AutoConfigurationEntryAutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);//添加到autoConfigurationEntries变量中,供后期使用
this.autoConfigurationEntries.add(autoConfigurationEntry);
//设置entries变量,导入的类名和元注解映射关系for (String importClassName : autoConfigurationEntry.getConfigurations()) {this.entries.putIfAbsent(importClassName, annotationMetadata);}
}
此处deferredImportSelector强转为AutoConfigurationImportSelector后,再次调用了getAutoConfigurationEntry方法。
AutoConfigurationImportSelector-getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {// 如果自动配置不可用,则返回 EMPTY_ENTRYif (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}// 获取注解的属性AnnotationAttributes attributes = getAttributes(annotationMetadata);// 获取候选自动配置类,此文关键List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 去除重复的自动配置类configurations = removeDuplicates(configurations);// 获取需要排除的自动配置类,spring.autoconfigure.exclude配置Set<String> exclusions = getExclusions(annotationMetadata, attributes);// 检查是否有被排除的自动配置类checkExcludedClasses(configurations, exclusions);// 去除被排除的自动配置类configurations.removeAll(exclusions);// 使用 ConfigurationClassFilter 过滤自动配置类configurations = getConfigurationClassFilter().filter(configurations);// 发送自动配置事件fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}
该方法的作用是根据给定的注解元数据获取自动配置项,对于自动配置的加载,关键在getCandidateConfigurations(annotationMetadata, attributes)
。
AutoConfigurationImportSelector-getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//从类路径的META-INF/spring中载入名为AutoConfiguration全限定名的类List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).getCandidates();Assert.notEmpty(configurations,"No auto configuration classes found 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;
}
该方法的ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
会拼凑出META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
路径,用于加载定义的AutoConfiguration类。
ImportCandidates-ImportCandidates
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {Assert.notNull(annotation, "'annotation' must not be null");ClassLoader classLoaderToUse = decideClassloader(classLoader);//将META-INF/spring/%s.imports字符串格式化为指定的路径String location = String.format(LOCATION, annotation.getName());Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);List<String> importCandidates = new ArrayList<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();importCandidates.addAll(readCandidateConfigurations(url));}return new ImportCandidates(importCandidates);
}
在grouping.getImports()
获取到所有要导入的AutoConfigurationEntry后,通过processImports
进行处理
ConfigurationClassParser-processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,boolean checkForCircularImports) {// 如果没有可导入的类,则直接返回if (importCandidates.isEmpty()) {return;}// 检查循环导入if (checkForCircularImports && isChainedImportOnStack(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {// 将当前配置类推入导入栈中this.importStack.push(configClass);try {// 处理每个导入的类for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine imports// 如果候选类是 ImportSelector 的子类,则交由它来决定导入哪些类Class<?> candidateClass = candidate.loadClass();ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,this.environment, this.resourceLoader, this.registry);Predicate<String> selectorFilter = selector.getExclusionFilter();if (selectorFilter != null) {exclusionFilter = exclusionFilter.or(selectorFilter);}if (selector instanceof DeferredImportSelector deferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);}else {String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);}}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitions// 如果候选类是 ImportBeanDefinitionRegistrar 的子类,则交由它来注册更多的 Bean 定义Class<?> candidateClass = candidate.loadClass();ImportBeanDefinitionRegistrar registrar =ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,this.environment, this.resourceLoader, this.registry);configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration class// 如果候选类不是 ImportSelector 或 ImportBeanDefinitionRegistrar 的子类,则将其作为 @Configuration 类来处理this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);}}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);}finally {this.importStack.pop();}}
}
以MybatisPlusLanguageDriverAutoConfiguration
自动配置为例,会通过processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
进行处理。
ConfigurationClassParser-processConfigurationClass
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {// 如果该配置类被标记为跳过,则直接返回,不需要再处理if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}// 如果已经存在同名的配置类,则判断两者的导入情况并合并ConfigurationClass existingClass = this.configurationClasses.get(configClass);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);}}// 递归地处理该配置类及其父类的继承关系,解析 Bean 定义SourceClass sourceClass = asSourceClass(configClass, filter);do {sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);// 将该配置类加入到 configurationClasses 中this.configurationClasses.put(configClass, configClass);
}
ConfigurationClassParser-doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// 如果该配置类被@Component注解标记,则递归处理任何嵌套类。processMemberClasses(configClass, sourceClass, filter);}// 处理 @PropertySourcefor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.propertySourceRegistry != null) {this.propertySourceRegistry.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 immediatelySet<BeanDefinitionHolder> scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// 检查扫描的定义集是否有任何进一步的配置类,并在需要时递归解析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());}}}}// 处理@ImportprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// 处理@ImportResourceAnnotationAttributes 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);// 找到超类,返回其注释元数据并递归return sourceClass.getSuperClass();}}// 没有超类,完成return null;}
总结
一张图说明整个自动配置加载解析流程