【springboot配置文件加载源码分析】

在Spring Boot的源码中,配置文件的加载是在应用程序启动的早期阶段进行的。具体来说,配置文件加载的主要步骤发生在SpringApplication类的run()方法中的prepareEnvironment方法中,真正读取我们的配置文件还是PropertySourceLoader。

本篇博客适合准备看源码,和想了解配置文件加载大体逻辑的同学。
本篇文章主要粘贴了加载配置文件的主要处理逻辑的源码,方便各位同学直接定位关键代码,辅助大家了解配置文件被处理的过程。

以下是Spring Boot源码中加载配置文件的主要步骤:

  1. prepareEnvironment()方法: 应用程序的入口点是SpringApplication类的run(),加载配置的方法入口run()中调用的prepareEnvironment()方法。初始化environment对象用于后续存储环境信息,以及后续处理逻辑的入口都在这个方法。

  2. ApplicationEnvironmentPreparedEvent 事件: 发布环境准备事件,通过spring事件发布机制去处理环境对象。关键代码 listeners.environmentPrepared(bootstrapContext, environment);

    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
    			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    		// Create and configure the environment
    		ConfigurableEnvironment environment = getOrCreateEnvironment();
    		configureEnvironment(environment, applicationArguments.getSourceArgs());
    		ConfigurationPropertySources.attach(environment);
    		//本行代码是解析配置的核心代码
    		listeners.environmentPrepared(bootstrapContext, environment);
    		DefaultPropertiesPropertySource.moveToEnd(environment);
    		configureAdditionalProfiles(environment);
    		bindToSpringApplication(environment);
    		if (!this.isCustomEnvironment) {
    			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
    					deduceEnvironmentClass());
    		}
    		ConfigurationPropertySources.attach(environment);
    		return environment;
    	}
    

    这行代码我们继续debug的话会发现,核心逻辑就是发布了一个ApplicationEnvironmentPreparedEvent事件,通过debug可以发现有以下7个监听器对该事件做了监听。虽然有7个监听器,从类名上看我肯定是重点关注EnvironmentPostPorcessorApplicationListener
    在这里插入图片描述

  3. EnvironmentPostProcessor接口:我们继续跟踪EnvironmentPostPorcessorApplicationListener监听器的主要处理逻辑会发现,该监听器的逻辑主要是调用用EnvironmentPostProcessor接口。直接上代码 EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent

    private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
    	ConfigurableEnvironment environment = event.getEnvironment();
    	SpringApplication application = event.getSpringApplication();
    	for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(event.getBootstrapContext())) {
    		postProcessor.postProcessEnvironment(environment, application);
    	}
    }
    

    可以看到上面代码主要就是遍历EnvironmentPostProcessor接口并执行postProcessEnvironment方法,这个地方会遍历哪些接口,大家就自行打断点吧,关键的处理器为ConfigDataEnvironmentPostProcessor这个接口postProcessEnvironment方法实现比较复杂,核心逻辑都在里面,分析到里面的方法我已经不行了。

    这个地方所遍历接口,也是springboot通过其SPI机制,在初始化SpringApplication时set进去的

  4. load()方法:通过我们不断的debug postProcessEnvironment方法,好像找到加载配置文件的主线了,load方法一看名字就是我们重点关注的对象!!!

    下面是postProcessEnvironment到load的调用栈信息: 在这里插入图片描述
    看一下load方法吧(下面代码有注释哦!):

    	public ConfigData load(ConfigDataLoaderContext context, StandardConfigDataResource resource)
    			throws IOException, ConfigDataNotFoundException {
    		if (resource.isEmptyDirectory()) {
    			return ConfigData.EMPTY;
    		}
    		ConfigDataResourceNotFoundException.throwIfDoesNotExist(resource, resource.getResource());
    		StandardConfigDataReference reference = resource.getReference();
    		Resource originTrackedResource = OriginTrackedResource.of(resource.getResource(),
    				Origin.from(reference.getConfigDataLocation()));
    		String name = String.format("Config resource '%s' via location '%s'", resource,
    				reference.getConfigDataLocation());
    				//获取properties,yml加载器,加载对应的资源生成propertySources,封装成ConfigData
    		List<PropertySource<?>> propertySources = reference.getPropertySourceLoader().load(name, originTrackedResource);
    		return new ConfigData(propertySources);
    	}
    

关键代码就暂时分析到这儿,当前中间还有很多的逻辑,目前能力有限暂时到这儿,后续也会对该篇博客持续更新!!!!

总结一下吧

发布ApplicationEnvironmentPreparedEvent 事件进行一系列的处理,EnvironmentPostPorcessorApplicationListener监听处理器,调用EnvironmentPostProcessor接口处理环境加载配置,关键的接口实现是ConfigDataEnvironmentPostProcessor类去处理,最后是读取我们本地资源,根据不同的配置文件找到对应的PropertySourceLoader去加载我们
的properties,yaml 得到PropertySource,然后最后经过层层的封装,最后还是会放到environment中

问题遗留:配置文件优先级、远程配置如何加载的源码体现,后面再补充

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/288328.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker安装Flarum(开源论坛)

Flarum介绍安装命令 #---------------------------------------------------------- mkdir -p /opt/flarum && cd /opt/flarum #---------------------------------------------------------- docker run -p 8888:8888 --name flarum \ --restartalways \ -v /opt/flar…

靠着这份年终总结,我涨薪8K,成为领导眼中最闪亮的星~

2023 年即将接近尾声&#xff0c;各大公司的“测试媛/猿”们又到了提交年终总结报告的时候了。 每年到这个时候都是抓耳挠腮、冥思苦想的时候&#xff0c;猛然一想&#xff0c;今年跟去年做的事情好像差不多&#xff0c;那么年终总结可以敷衍了事么&#xff1f; 当然是不可以…

chatGPT带你学习设计模式 (二)抽象工厂模式(创建型模式) GURU

深入理解抽象工厂模式 引言 在面向对象编程中&#xff0c;对象的创建是一个常见且关键的挑战。尤其在需要管理一系列相关对象的创建时&#xff0c;传统的对象创建方法&#xff08;如直接使用 new 关键字&#xff09;可能导致代码的高耦合和低灵活性。这时&#xff0c;抽象工厂…

rime中州韵小狼毫 中英互绎 滤镜

英文在日常生活中已经随处可见&#xff0c;我们一般中英互译需要使用专业的翻译软件来实现。但如果我们在输入法中&#xff0c;在输入中文的时候&#xff0c;可以顺便瞟一眼对应的英文词汇&#xff0c;或者在输入英文的时候可以顺便了解对应的中文词汇&#xff0c;那将为我们的…

【Qt第三方库】QXlsx库——对 Excel 文件进行相关操作

0 前言 关键词&#xff1a;Qt&#xff1b;Excel&#xff1b;QXlsx&#xff1b;QInt 简介&#xff1a; QXlsx 是第三方开源的库&#xff0c;能够对 Excel 文件进行相关操作&#xff08;读写等&#xff09; 地址&#xff1a; QXlsx官网 QXlsx的Github主页 1 快速上手 对于第一次…

设置代理IP地址对网络有什么影响?爬虫代理IP主要有哪些作用?

在互联网的广泛应用下&#xff0c;代理IP地址成为了一种常见的网络技术。代理IP地址可以改变用户的上网行为&#xff0c;进而影响网络访问的速度和安全性。本篇文章将探讨设置代理IP地址对网络的影响&#xff0c;以及爬虫代理IP的主要作用。 首先&#xff0c;让我们来了解一下代…

【Java】实验三 抽象类与接口

实验名称 实验三 抽象类与接口 实验目的 1. 深刻理解抽象类、接口的意义。 2. 熟练掌握抽象类和接口的定义、继承抽象类以及实现接口的方法。 3. 理解和掌握多态。 实验内容 &#xff08;一&#xff09;抽象类实验&#xff1a;项目源码中新建一个ahpu.shape的包&a…

Transformer从菜鸟到新手(一)

引言 这是从Transformer到LLM(大语言模型)系列的第一篇文章&#xff0c;几乎所有的大语言模型都是基于Transformer结构&#xff0c;因此本文回顾一下Transformer的原理与实现细节&#xff0c;包括分词算法BPE的实现。最终利用从零实现的Transformer模型进行英中翻译。 本文主…

IOS:Safari无法播放MP4(H.264编码)

一、问题描述 MP4使用H.264编码通常具有良好的兼容性&#xff0c;因为H.264是一种广泛支持的视频编码标准。它可以在许多设备和平台上播放&#xff0c;包括电脑、移动设备和流媒体设备。 使用caniuse查询H.264兼容性&#xff0c;看似确实具有良好的兼容性&#xff1a; 然而…

Windows系统镜像检测修复建议

当通过镜像检测功能检测出Windows操作系统磁盘上有残留驱动项、系统中存在残留Xen驱动或者存在禁止安装驱动属性设置等异常检测项时&#xff0c;您可以参考本文的操作指导进行修复。 清理注册表残留驱动 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control注册表树包含了控…

c++基础(对c的扩展)

文章目录 命令空间引用基本本质引用作为参数引用的使用场景 内联函数引出基本概念 函数补充默认参数函数重载c中函数重载定义条件函数重载的原理 命令空间 定义 namespace是单独的作用域 两者不会相互干涉 namespace 名字 { //变量 函数 等等 }eg namespace nameA {int num;v…

TextView ClickableSpan 事件分发的坑

TextView 的 ClickableSpan 有两个坑&#xff1a; 默认情况下&#xff0c;点击 ClickableSpan 的文本时会同时触发绑定在 TextView 的监听事件&#xff1b;默认情况下&#xff0c;点击 ClickableSpan 的文本之外的文本时&#xff0c;TextView 会消费该事件&#xff0c;而不会传…

MySQL运维实战(2.2)忘记密码如何处理

作者&#xff1a;俊达 引言 当你突然忘记了一个普通用户的密码&#xff0c;而又想着通过管理员账号去改密码时&#xff0c;却猛的发现所有管理员账号的密码都离谱地被你忘了。嗨呀&#xff0c;这可真是个尴尬的大麻烦&#xff01;root账户通常是MySQL中的大boss&#xff0c;你…

Redis(一)

1、redis Redis是一个完全开源免费的高性能&#xff08;NOSQL&#xff09;的key-value数据库。它遵守BSD协议&#xff0c;使用ANSI C语言编写&#xff0c;并支持网络和持久化。Redis拥有极高的性能&#xff0c;每秒可以进行11万次的读取操作和8.1万次的写入操作。它支持丰富的数…

【LeetCode:69. x 的平方根 | 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

程序员提问的艺术:28.4K Star指南,告别成为办公室讨厌鬼!

Github: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way 原文&#xff1a;http://www.catb.org/~esr/faqs/smart-questions.html ✅为什么讨厌某些提问者 未自行尝试解决问题&#xff1a; ❌“怎么用Java写一个排序算法&#xff1f;” &#x1f44d;&#…

Plantuml之EBNF语法介绍(二十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

java spring核心技术AOP面向切面编程图文并茂包含例子demo

base Aspect-oriented programming面向切面的程序设计用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)场景: 权限认证,日志和事务处理.demo 基本背景 // 背景: 1. 模拟数据库操作增删改查 …

tomcat session cookie值设置逻辑

tomcat session cookie 值设置&#xff0c;tomcat jsessionid设置 ##调用request.getSession() Controller RequestMapping("/cookie") public class CookieController {RequestMapping("/tomcatRequest")ResponseBodypublic String tomcatRequest(HttpS…

CentOS 7 实战指南:文本处理命令详解

前言 在Linux系统中&#xff0c;文本处理是非常基础却又必不可少的一项技能。如果你正在使用CentOS系统&#xff0c;那么学会如何利用文本操作命令来高效地处理文本文件无疑将会是一个强有力的工具。 本篇文章将介绍一些最常用和最实用的文本操作命令&#xff0c;并通过详尽的…