IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot配置文件加载过程 -> 正文阅读

[Java知识库]SpringBoot配置文件加载过程

参考:Springboot源码之application.yaml读取过程

当SpringBoot版本<2.4.0时:

SpringBoot配置文件一般为application.ymlapplication.properties等,其加载流程在SpringApplicationrun()方法中的ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);中完成,当环境准备好会触发EventPublishingRunListener implement SpringApplicationRunListenerenvironmentPrepared()方法,该方法广播ApplicationEnvironmentPreparedEvent,该事件有一个ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered监听器,该类用于加载配置文件。以上具体的调用过程如下:
在这里插入图片描述
具体看看ConfigFileApplicationListener这个类如何加载配置文件的:

public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
	...
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		// 向下转型
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
		}
		if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent(event);
		}
	}

	private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
		// 获取所有的EnvironmentPostProcessor对象
		List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
		// this对象也是一个EnvironmentPostProcessor,加入
		postProcessors.add(this);
		AnnotationAwareOrderComparator.sort(postProcessors);
		for (EnvironmentPostProcessor postProcessor : postProcessors) {
		// 遍历进行环境后置处理
		// 当处理到this时,加载文件,会调用this.postProcessEnvironment	
		postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
		}
	}
	...
		@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		addPropertySources(environment, application.getResourceLoader());
	}

	protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
		RandomValuePropertySource.addToEnvironment(environment);
		// 正式开始load
		new Loader(environment, resourceLoader).load();
	}
}

		// 这里用来循环location,点开getSearchLocations()可以看到配置文件的路径搜索顺序(LinkedHashSet是有序的)如下:
		// "file:./config/"
		// "file:./config/*/"
		// "file:./"
		// "classpath:/config/"
		// "classpath:/"
		private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
			getSearchLocations().forEach((location) -> {
				boolean isDirectory = location.endsWith("/");
				// 用来循环配置文件名称,一般只有一个就是application,除非设置spring.profiles.active项
				Set<String> names = isDirectory ? getSearchNames() : NO_SEARCH_NAMES;
				names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
			});
		}
		
		private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,
				DocumentConsumer consumer) {
			if (!StringUtils.hasText(name)) {
				for (PropertySourceLoader loader : this.propertySourceLoaders) {
					if (canLoadFileExtension(loader, location)) {
						load(loader, location, profile, filterFactory.getDocumentFilter(profile), consumer);
						return;
					}
				}
				throw new IllegalStateException("File extension of config file location '" + location
						+ "' is not known to any PropertySourceLoader. If the location is meant to reference "
						+ "a directory, it must end in '/'");
			}
			Set<String> processed = new HashSet<>();
			// PropertySourceLoader有两个实现类:PropertiesPropertySourceLoader和YamlPropertySourceLoader
			// 前者用于搜索properties和xml文件
			// 后者用于搜索yml和yaml文件
			for (PropertySourceLoader loader : this.propertySourceLoaders) {
				// 遍历后缀文件名,
				for (String fileExtension : loader.getFileExtensions()) {
					if (processed.add(fileExtension)) {
						// 这里load
						loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory,
								consumer);
					}
				}
			}
		}

当SpringBoot版本>=2.4.0时:

上文中ConfigFileApplicationListener类于2.4.0版本被废弃,取而代之的是ConfigDataEnvironmentPostProcessor,通过这两个类的注释也可以看出:
在这里插入图片描述
在这里插入图片描述之前加载application.yml or properties文件和springboot是耦合在一个ConfigFileApplicationListener中,也就是说,只有调用springboot的这个监听器才能解析配置文件,而现在SpringBoot这里抽象出了加载文件的过程。

先来看一下org.springframework.boot:spring-boot.jar包下的 M E T A ? I N F META-INF META?INFspring.factories文件,需要注意以下三个key:value:
在这里插入图片描述
看到下面两个接口属于同一个包,显然是有一定联系的。看看它们的注释:

ConfigDataLocationResolver: Strategy interface used to resolve {@link ConfigDataLocation locations} into one or more {@link ConfigDataResource resources}.
ConfigDataLoader: Strategy class that can be used to load {@link ConfigData} for a given{@link ConfigDataResource}.

他们都是策略模式的上层接口,之间的联系如下图:
在这里插入图片描述
再看第一个接口:

PropertySourceLoader: to load a {@link PropertySource}.

实际上,在加载springboot配置文件的过程中StandardConfigDataSource extends ConfigDataSource中通过字段StandardConfigDataReference reference 的字段方法PropertySourceLoader.load()来实现ConfigDataLoader.load()。这个StandardConfigDataReference既有 ConfigDataLocation 也有PropertySourceLoader,起到了承上启下的reference作用。结构图如下:
在这里插入图片描述
至于StandardConfigDataLoader怎么调用的,我就不画图了,流程如下:
ConfigDataEnvironmentPostProcessorpostProcessEnvironment() → \rightarrow ConfigDataEnvironmentprocessAndApply() → \rightarrow 同类中的processInitial() → \rightarrow ConfigDataEnvironmentContributorswithProcessedImports() → \rightarrow ConfigDataImporterresolveAndLoad() → \rightarrow 同类的load() → \rightarrow ConfigDataLoadersload() → \rightarrow StandardConfigDataLoaderload()

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:22:29  更:2022-03-04 15:24:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:29:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码