【BlossomConfig】SpringCloud项目是如何对bootstrap配置文件进行加载的?

文章目录

  • bootstrap配置文件的读取

网关项目源码
RPC项目源码
配置中心项目源码

bootstrap配置文件的读取

我们首先来了解一下springboot是如何做配置管理的。
了解了springboot对配置文件的管理,我们就能知道为什么springcloud类型的项目要使用bootstrap配置文件了。
关于SpringBoot是如何加载application和bootstrap配置文件的底层原理这里就不再次赘述了,大家可以移步到知识星球内部的如下位置进行学习。
在这里插入图片描述

简单回忆一下,既然和配置文件相关,那么我们找到spring的run方法中的如下这行代码然后往下分析即可。

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);

因为通过上面的学习我们知道Environment中存储了我们项目的所有配置信息。
这里我们着重分析一下这一行代码中都做了多少事情。

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {ConfigurableEnvironment environment = this.getOrCreateEnvironment();this.configureEnvironment(environment, applicationArguments.getSourceArgs());ConfigurationPropertySources.attach(environment);listeners.environmentPrepared(bootstrapContext, environment);DefaultPropertiesPropertySource.moveToEnd(environment);Assert.state(!environment.containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");this.bindToSpringApplication(environment);if (!this.isCustomEnvironment) {EnvironmentConverter environmentConverter = new EnvironmentConverter(this.getClassLoader());environment = environmentConverter.convertEnvironmentIfNecessary(environment, this.deduceEnvironmentClass());}ConfigurationPropertySources.attach(environment);return environment;
}

首先是基于当前环境,创建一个环境对象。
在这里插入图片描述
这里由于我们的项目是Web项目,所以创建的是:StandardServletEnvironment
并且这里会层层的通过extends的继承关系,不断的初始化父类。
最终,又会回到子类的实现。
在这里插入图片描述
在这里插入图片描述
通过我们前面的了解,我们知道,其实这些代码的作用就是往容器末尾不断的添加配置文件的信息。
不过上面的创建的是系统的环境,而我们自己编写的配置文件的信息的加载,并不是在这里完成的。
我们最终读取配置文件的代码,是通过监听器的方式来完成的。

listeners.environmentPrepared(bootstrapContext, environment);

而事件监听是spring提供的一个非常重要的扩展机制,很多功能我们都可以基于监听器这种方式来实现。
我们只需要负责发布事件,对应的事件监听器就执行相应的代码来处理这个事件。
可以发现,在我们的环境创建好之后,然后就会发布一个环境预备的事件。那么此时就等待对应的监听器进行处理即可。

public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}

事件发布之后,通过层层的下叠,最终,spring通过拿到所有注册的监听器的方式,让这些监听器判断当前事件是否是由自己处理的,如果是,就处理当前事件即可。
在这里插入图片描述
在这里插入图片描述
这里我们可以知道,其实我们发布的就是一个环境预备完成的事件。
按图索骥即可。
在这里插入图片描述
继续往下找,就会发现,通过迭代器的方式,会通过这些后置处理器对我们的配置文件信息进行处理。
在这里插入图片描述
再早期的版本中,用的是ConfigFile进行配置文件处理。
在这里插入图片描述
只不过版本高了就废弃了,而是用其他几个。
不过大致的意思也差不多。
因此,到此为止,其实我们大概就知道了,当项目流程到达这一步的时候,其实Spring做的事情就是通过IO流的方式去读取所有的配置文件信息,并且对他们进行解析。
在这里插入图片描述
这里我们跳到看ConfigDataEnvironment即可
在这里插入图片描述
因此,通过上面我们可以看到,只要我们再规定的位置编写配置文件,spring就可以帮助我们去加载这些配置文件。
并且,我们也可以通过实现自己的监听器的方式,再触发对应的环境准备完毕事件之后,使用我们的监听器去处理我们的配置文件。
这里,我通过实现一下按照上面的方法,实现监听器的方式,来加载配置文件信息。
特别注意, 在 Spring Boot 中,ApplicationEnvironmentPreparedEvent事件发生在 ApplicationContext 创建之前,这意味着使用 @Component 或 @Configuration 注解的方式无法确保监听器被及时注册。
相反,我需要在应用启动时手动注册该监听器。或者使用spring.factories的方式来完成自动装配。

# Application Listeners
org.springframework.context.ApplicationListener=\
blossom.project.config.core.listener.BootstrapApplicationListener
package blossom.project.config.core.listener;import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.stereotype.Component;import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;/*** @author: ZhangBlossom* @date: 2023/12/26 22:33* @contact: QQ:4602197553* @contact: WX:qczjhczs0114* @blog: https://blog.csdn.net/Zhangsama1* @github: https://github.com/ZhangBlossom* BootstrapListener类* 用于在项目启动的时候通过环境准备事件完成对bootstrap配置文件的读取加载* 特别注意* 在 Spring Boot 中,ApplicationEnvironmentPreparedEvent* 事件发生在 ApplicationContext 创建之前,* 这意味着使用 @Component 或 @Configuration 注解的方式无法确保监听器被及时注册。* 相反,我需要在应用启动时手动注册该监听器。*/
//@Component
//@Configuration
//@AutoConfiguration
public class BootstrapListenerimplements ApplicationListener<ApplicationEnvironmentPreparedEvent> {static {System.out.println("成功被加载...");}@Overridepublic void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {MutablePropertySources propertySources = event.getEnvironment().getPropertySources();Properties properties = new Properties();try {InputStream inputStream = BootstrapListener.class.getClassLoader().getResourceAsStream("bootstrap" +".properties");properties.load(inputStream);ConcurrentHashMap<Object,Object> cache = new ConcurrentHashMap<>();for (Map.Entry<Object, Object> entry : properties.entrySet()) {cache.put(entry.getKey(),entry.getValue());}propertySources.addLast(new OriginTrackedMapPropertySource("bootstrap.properties",properties));}catch (Exception e){e.printStackTrace();}}
}
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ConfigApplication {public static void main(String[] args) {SpringApplication app = new SpringApplication(ConfigApplication.class);app.addListeners(new BootstrapListener());ConfigurableApplicationContext context = app.run(args);BootstrapListener bean = context.getBean(BootstrapListener.class);System.out.println(bean);ConfigurableEnvironment environment = context.getEnvironment();System.out.println(environment);}
}

运行代码之后发现,成功了。
在这里插入图片描述
当然,我还发现了另一种解决方法,就是使用@PropertySource注解。
但是使用这个注解的一个问题在于他只能解析比较常规的配置文件。对于txt这种应该是解析不了。
而且很明显,我们不应该再代码中硬编码。所以我个人比较倾向于使用监听器的方式去解析配置文件。

@Configuration
@PropertySource("classpath:bootstrap.yml")
public class PropertySourceConfig {
}

因此,我们的第一个问题,如何处理bootstrap类型的文件的问题,就已经解决了。

接下来我们可以研究一下,Nacos是如何实现配置文件的加载的,这也对我们上面分析的逻辑有确定作用。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国RAKsmart:裸机云站群服务器配置详解

裸机云&#xff0c;也称为物理云&#xff0c;是一种云服务模式&#xff0c;它为用户提供了接近物理机性能的云服务器。而站群服务器&#xff0c;则是为了支持多个网站或应用程序的运行而设计的服务器。美国RAKsmart作为一家知名的云服务提供商&#xff0c;其裸机云站群服务器配…

【大模型】大模型发展历程,从GPT开始到Grok-1.5霸榜

目录 大模型发展历程 大模型发展历程 2018年6月&#xff0c;openAI发布GPT1&#xff1b;2019年2月&#xff0c;发布GPT2&#xff1b;2020年6月&#xff0c;发布GPT-3。 2022年11月30日&#xff0c;openAI发布ChatGPT。 2023年3月14日&#xff0c;GPT-4 发布。 2023年7月18日…

Proteus 12V to 5V buck电路仿真练习及遇到的一些问题汇总

基础电路仿真实验记录贴&#xff01;&#xff01;&#xff01;如有写的不对的地方欢迎交流指正&#xff01;&#xff01;&#xff01; 平台&#xff1a;PC win10 软件&#xff1a;Proteus8.10 仿真目标&#xff1a;buck降压电路&#xff08;PWM控制输出电压&#xff09; 写在…

八皇后问题解决过程字符串可视化

查找到问题&#xff0c;暂停600毫秒&#xff0c; 穷举本行&#xff0c;200毫秒 返回上一层之前&#xff0c;会弹出回滚上一层&#xff08;4&#xff0c;X&#xff09;&#xff0c;并暂停600毫秒 成功返回时&#xff0c;会弹出上一层具体数据如&#xff08;4&#xff0c;3&a…

Java | Leetcode Java题解之第3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; class Solution {public int lengthOfLongestSubstring(String s) {// 哈希集合&#xff0c;记录每个字符是否出现过Set<Character> occ new HashSet<Character>();int n s.length();// 右指针&#xff0c;初始值为 -1&#…

分治——归并排序算法

例题一 解法&#xff08;归并排序&#xff09;&#xff1a; 算法思路&#xff1a; 归并排序的流程充分的体现了「分⽽治之」的思想&#xff0c;⼤体过程分为两步&#xff1a; ◦ 分&#xff1a;将数组⼀分为⼆为两部分&#xff0c;⼀直分解到数组的⻓度为 1 &#xff0c;使…

【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

【Web应用技术基础】CSS(6)——使用 HTML/CSS 实现 Educoder 顶部导航栏

第一题&#xff1a;使用flex布局实现Educoder顶部导航栏容器布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Educoder</title><script src"https://cdn.staticfile.org/jquery/1.1…

EDM营销文案的撰写技巧?如何提升转化率?

EDM营销文案与SEO策略如何结合&#xff1f;怎么写有效营销邮件&#xff1f; EDM仍然是一种高效且经济的推广手段。撰写优质的EDM营销文案&#xff0c;不仅可以提升品牌形象&#xff0c;还能有效促进销售转化。那么&#xff0c;如何撰写出引人入胜的EDM营销文案呢&#xff1f;A…

Anaconda conda常用命令

查看配置信息&#xff1a;conda config --show 恢复默认源&#xff1a;conda config --remove-key channels 创建虚拟环境&#xff1a;conda create -n env_name python3.8&#xff0c;表示创建python版本为3.8、名字为env_name的虚拟环境。 查看虚拟环境&#xff1a;conda …

Python点云处理(二十二)基于XGBoost的点云分类算法

目录 0 简述1 XGBoost2 点云特征向量构建3 用XGBoost进行分类4 代码实现5 结果展示0 简述 点云分类是计算机视觉领域中的一个重要任务,其主要目标是将三维空间中的点云数据划分为不同的类别。点云是由大量的三维点组成的数据集,通常由激光雷达或结构光等传感器采集而来。点云…

KNN算法 | K近邻:KD Tree、球树、KNN数据下采样策略

目录 一. KNN算法实现方式1. 蛮力实现(brute)2. KD树(kd_tree)3. 球树(ball_tree) 二. KD Tree算法1. 构建方式2. KD Tree 查找最近邻 三. 球树(Ball Tree)1. 构建方式 四. KNN评价1. 优点2. 缺点 五. 延申1. KNN数据下采样策略策略1策略2策略3策略4 Condensed Nearest Neighbo…

Leo赠书活动-23期 【Python数据分析】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

大模型遇上心理健康咨询:MeChat、QiaoBan、SoulChat、MindChat四大心理健康领域微调模型总结

HealthX AI 2023-09-18 08:05 江苏 以下文章来源于老刘说NLP &#xff0c;作者刘焕勇 老刘说NLP. 老刘&#xff0c;NLP开源爱好者与践行者。主页&#xff1a;https://liuhuanyong.github.io。老刘说NLP&#xff0c;将定期发布语言资源、工程实践、技术总结等内容&#xff0c;…

C语言 06 无符号数

所有的数据底层都是采用二进制来进行保存的。 第一位用于保存符号位。 如果不考虑这个符号位&#xff0c;那么所有的数都是按照正数来表示。 比如考虑了符号位的 char 类型&#xff1a; 考虑符号表示范围&#xff1a;-128 ~ 127不考虑符号&#xff1a;0 ~ 255 直接使用这些不…

SublimeText3多次保存自动弹出窗口

文章目录 1. 取消自动更新2. 阻止程序与服务器进行通信3. 尝试保存&#xff0c;弹出不出现 1. 取消自动更新 在settings中加入&#xff1a; "update_check": false2. 阻止程序与服务器进行通信 在/etc/hosts&#xff08;Linux/macOS&#xff09;或C:\Windows\Syst…

C++代码eSpeak库使用示例

要将 eSpeak 库生成的 PCM 数据转换为 WAV 格式并保存&#xff0c;你可以使用 C 的标准文件操作来创建 WAV 文件&#xff0c;并将 PCM 数据写入其中。 #include <iostream> #include <vector> #include <cstdint> #include <cstring>extern "C&q…

Docker中常见的命令行

1 docker的全部命令 docker attach #连接到正在运行中的容器 docker build #使用 Dockerfile 创建镜像 docker builder #管理builds docker builder prune #清除build缓存 docker checkpoint #管理checkpoints docker checkpoint create #从正在运行的容器创建检…

数据结构——集合和静态查找表

集合&#xff1a;数据元素同属一个集合&#xff0c;具有关键字值&#xff08;键值&#xff09;key&#xff0c;数据元素之间没有逻辑关系&#xff0c;集合两大核心操作是查找和排序 查找表&#xff1a;用于查找的数据结构&#xff0c;分为静态查找表和动态查找表&#xff0c;静…

求将TXT文本转换为Word文档的方法

一&#xff0c;前言 在现代办公环境中&#xff0c;文本文件的转换已成为一项常见的任务。其中&#xff0c;将TXT文本转换为Word文档是最常见的需求之一。这种转换不仅可以帮助我们更好地编辑和格式化文本&#xff0c;还可以提高文件的安全性和兼容性。本文将详细介绍如何将TXT…