Detailed Explanation of Spring Boot 3.x Automatic Configuration

Based on the Spring Boot 3.1.0 series of articles

  1. Spring Boot source code reading initialization environment construction
  2. Detailed explanation of the overall startup process of the Spring Boot framework
  3. Detailed Explanation of Spring Boot System Initializer
  4. Detailed explanation of Spring Boot listener
  5. Detailed explanation of Spring Boot banner
  6. Spring Boot property configuration analysis
  7. Analysis of Spring Boot property loading principle
  8. Analysis of Spring Boot exception reporter
  9. Detailed Explanation of Spring Boot 3.x Automatic Configuration

Spring Boot :3.1
Java: 17

foreword

The automatic configuration in Spring Boot 3.x uses META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports , instead of META-INF/spring.factories, this change has actually changed in 2.7

Version 2.6.9 Documentation Introduction

insert image description here
Introduction to version 2.7.0

insert image description here
There is a detailed introduction to creating your own Starter in the document, "Spring Boot Chinese Reference Guide - Creating Your Own Automatic Configuration"

loading principle

The automatic configuration loading entry of Spring Boot 3.x is that META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports Spring Boot will read the automatic configuration class in the file and instantiate it. We use this file as the entry.

If you are a novice and have no information to check, you can use the global file search function of the IDE to search for keywords. For example, the org.springframework.boot.autoconfigure.AutoConfiguration.imports results of my search are as follows, and then you can judge the entry to load the file by breaking points.

insert image description here

It can be seen that the loading of the file is AutoConfigurationImportSelectorhandled by the class, but AutoConfigurationImportSelectorhow the class is loaded.
Through the stack of breakpoints, it can be seen that the loading is used in the Spring framework refresh(). invokeBeanFactoryPostProcessorsIts function is to load additionally defined beans into the context before instantiating the beans. We start from scratch, and those who are capable can master the method and read it by themselves.

stack information

insert image description here

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

The function of this method is to instantiate and call the registeredBeanFactoryPostProcessor

getBeanFactoryPostProcessors()It is used to get all BeanFactoryPostProcessorthe instances, and BeanFactoryPostProcessorthe instances ApplicationContextInitializerare loaded into the context through the method. ApplicationContextInitializerThe loading principle can be understood through the previous article "Detailed Explanation of the Spring Boot System Initializer" .

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());Delegate processing to BeanFactoryPostProcessor.

PostProcessorRegistrationDelegate-invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    

		Set<String> processedBeans = new HashSet<>();
		//如果beanFactory 是BeanDefinitionRegistry的实现,先处理BeanDefinitionRegistryPostProcessors
		if (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 的 BeanDefinitionRegistryPostProcessor
			String[] 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);
			
//处理BeanDefinitionRegistryPostProcessors
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// 再处理 Ordered 的 BeanDefinitionRegistryPostProcessor
			postProcessorNames = 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();
			}

			// 处理所有 BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
    
    
			// 处理普通的上下文中的BeanFactoryPostProcessor
	invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		//获取所有常规化Bean,但不初始化,保留让后期的post-processors处理
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		
		//分离实现PriorityOrdered、Ordered和其他的BeanFactoryPostProcessors
		List<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的BeanFactoryPostProcessors
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//处理实现了Ordered的BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
    
    
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后处理其他的BeanFactoryPostProcessors
		List<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()); is the key point for handling auto-configuration

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

BeanDefinitionRegistryPostProcessorThe interface inherits the BeanFactoryPostProcessor interface, which allows modifying, adding, and deleting the Bean definition information registered in the container before initializing the Bean instance

In the SpringBoot-Demo of this example, there is only one BeanDefinitionRegistryPostProcessor implementation, namelyConfigurationClassPostProcessor

ConfigurationClassPostProcessor-postProcessBeanDefinitionRegistry

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    
    
//计算hashcode
		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);
	}

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 content
			if (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 ConfigurationClass
		if (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();
		}
	}

The code here is very long, and the parsing of the configuration class parser.parse(candidates)is done in .
parserExamples of variables are: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();
	}

At the beginning, we already know that the actual parsing of the auto-configuration class is that AutoConfigurationImportSelectorAutoConfigurationImportSelector implements DeferredImportSelectorthe interface, and here happens to be used deferredImportSelectorHandlerto handle all deferredImportSelectorHandler instances. See DeferredImportSelectorHandlerthe process in the following.

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

DeferredImportSelectorGroupingHandlerThe class is an auxiliary class for processing the DeferredImportSelector interface in Spring Boot, and is mainly used to group DeferredImportSelector according to the grouping.

Here, we need to pay attention handler.processGroupImports()to calling DeferredImportSelectorGroupingHandlerthe processGroupImports method of the class.

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

The first thing to pay attention to here grouping.getImports()is that the automatic configuration class is loaded here

DeferredImportSelectorGrouping-getImports

public Iterable<Group.Entry> getImports() {
    
    
	for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
    
    
//处理每个分组的DeferredImportSelectorHolder
		this.group.process(deferredImport.getConfigurationClass().getMetadata(),
				deferredImport.getImportSelector());
	}
	//返回需要导入的类
	return this.group.selectImports();
}

this.group.processIn AutoConfigurationImportSelectorthe inner class entered inAutoConfigurationGroup

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,获取AutoConfigurationEntry
	AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
		.getAutoConfigurationEntry(annotationMetadata);
	
//添加到autoConfigurationEntries变量中,供后期使用
this.autoConfigurationEntries.add(autoConfigurationEntry);
//设置entries变量,导入的类名和元注解映射关系
	for (String importClassName : autoConfigurationEntry.getConfigurations()) {
    
    
		this.entries.putIfAbsent(importClassName, annotationMetadata);
	}
}

Here, after deferredImportSelector is forced to AutoConfigurationImportSelector, the getAutoConfigurationEntry method is called again.

AutoConfigurationImportSelector-getAutoConfigurationEntry

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    
    
    // 如果自动配置不可用,则返回 EMPTY_ENTRY
	if (!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);
}

The function of this method is to obtain automatic configuration items according to the given annotation metadata, and the key to automatic configuration loading is 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;
}

This method ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())will piece together META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsthe path used to load the defined AutoConfiguration class.

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

After grouping.getImports()getting all the AutoConfigurationEntry to be imported, processImportsprocess it by

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

Taking MybatisPlusLanguageDriverAutoConfigurationautomatic configuration as an example, it will processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);be processed by

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

		// 处理 @PropertySource
		for (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 immediately
				Set<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());
					}
				}
			}
		}

		// 处理@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);
				// 找到超类,返回其注释元数据并递归
				return sourceClass.getSuperClass();
			}
		}

		// 没有超类,完成
		return null;
	}

Summarize

A picture illustrates the entire automatic configuration loading and parsing process
insert image description here

Guess you like

Origin blog.csdn.net/weixin_40972073/article/details/131736129
Recommended