前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot 3.x 自动配置详解

Spring Boot 3.x 自动配置详解

作者头像
阿提说说
发布2023-10-16 11:28:52
2.6K0
发布2023-10-16 11:28:52
举报
文章被收录于专栏:Java技术进阶Java技术进阶

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

代码语言:javascript
复制
	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

代码语言:javascript
复制
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()); 是处理自动配置的关键点

PostProcessorRegistrationDelegate-invokeBeanDefinitionRegistryPostProcessors

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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();
		}
	}

此处代码很长,对于配置类的解析,在parser.parse(candidates)中完成。

parser变量的实例为:ConfigurationClassParser

ConfigurationClassParser-parse

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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.process中进入到AutoConfigurationImportSelector的内部类AutoConfigurationGroup

AutoConfigurationImportSelector-AutoConfigurationGroup-process

代码语言:javascript
复制
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);
	}
}

此处deferredImportSelector强转为AutoConfigurationImportSelector后,再次调用了getAutoConfigurationEntry方法。

AutoConfigurationImportSelector-getAutoConfigurationEntry

代码语言:javascript
复制
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);
}

该方法的作用是根据给定的注解元数据获取自动配置项,对于自动配置的加载,关键在getCandidateConfigurations(annotationMetadata, attributes)

AutoConfigurationImportSelector-getCandidateConfigurations

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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;
	}

总结

一张图说明整个自动配置加载解析流程

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 加载原理
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档