spring cloud config server源码学习(一)
文章目录
- 1. 注解EnableConfigServer
- 2. ConfigServerAutoConfiguration
- 2.1 @ConditionalOnBean和@ConditionalOnProperty
- 2.2 @Import注解
- 2.2.1. EnvironmentRepositoryConfiguration.class
- 2.2.2. CompositeConfiguration.class
- 2.2.3. ResourceRepositoryConfiguration.class
- 2.2.4. ConfigServerEncryptionConfiguration.class
- 2.2.5. ConfigServerMvcConfiguration.class
- 2.2.6. ResourceEncryptorConfiguration.class
- 3. EnvironmentRepository
- 4. EnvironmentRepositoryConfiguration.class
- 5. rest接口
spring cloud config server 作为一个spring boot工程,到底是如何运行起来的?似乎如上一篇文章中那样,引入了starter,启动了注解,配置了git的信息,就可以获取到数据了。那具体的原理是什么呢?
1. 注解EnableConfigServer
@EnableConfigServer
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigServer {public static void main(String[] args) {SpringApplication.run(ConfigServer.class, args);}
}
可以看到启动类上加入注解@EnableConfigServer。我们查看该注解的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigServerConfiguration.class)
public @interface EnableConfigServer {}
这个注解的定义当中,通过Import注解加载Bean ConfigServerConfiguration.class :
@Configuration(proxyBeanMethods = false)
public class ConfigServerConfiguration {@Beanpublic Marker enableConfigServerMarker() {return new Marker();}class Marker {}}
这个Configuration类只是加载了一个 Bean Marker。
这是spring加载Bean的一种常用方式。
2. ConfigServerAutoConfiguration
在spring cloud config Server的jar中,org.springframework.boot.autoconfigure.AutoConfiguration.imports文件内包含了多个自动配置的类,其中就包括ConfigServerAutoConfiguration类。
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapOverridesAutoConfiguration
org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration
根据命名,可以看到各个自动配置类的功能,是启用bootstrap配置还是启用RSA加密等等。这里暂时先关注
ConfigServerAutoConfiguration类:
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(ConfigServerConfiguration.Marker.class)
@ConditionalOnProperty(name = ConfigServerProperties.PREFIX + ".enabled", matchIfMissing = true)
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class,ResourceEncryptorConfiguration.class })
public class ConfigServerAutoConfiguration {}
这个类的注解包含了三个重要的注解@ConditionalOnBean、@ConditionalOnProperty和@Import。
2.1 @ConditionalOnBean和@ConditionalOnProperty
当这两个注解出现在同一个类上的时候,两个Conditional条件必须同时满足,即ConfigServerConfiguration.Marker.class这个Bean存在的同时,还要满足Spring环境属性中存在 ConfigServerProperties.PREFIX + “.enabled” 属性且其值为 true,或者该属性缺失(由于 matchIfMissing = true)。这个PREFIX是spring.cloud.config.server。
这里刚好好上面通过@EnableConfigServer加载的Bean Marker.class呼应上。
2.2 @Import注解
Import注解引入了六个类要加载到spring context中。
2.2.1. EnvironmentRepositoryConfiguration.class
EnvironmentRepositoryConfiguration 是Spring Cloud Config Server中配置存储库的核心配置类。它负责创建和配置EnvironmentRepository实例,EnvironmentRepository用于从各种后端(如Git、SVN、本地文件系统等)获取配置属性。
定义和配置不同类型的EnvironmentRepository(如GitEnvironmentRepository、NativeEnvironmentRepository)。
通过注入不同的配置属性,来灵活配置不同类型的存储库。
2.2.2. CompositeConfiguration.class
CompositeConfiguration 负责配置和管理CompositeEnvironmentRepository。CompositeEnvironmentRepository允许将多个EnvironmentRepository组合在一起,以便从多个源获取配置。
配置CompositeEnvironmentRepository,将多个EnvironmentRepository实例组合成一个逻辑上的存储库。
提供从多个配置源合并配置属性的功能,以实现更复杂的配置管理场景。
2.2.3. ResourceRepositoryConfiguration.class
ResourceRepositoryConfiguration 负责配置与管理资源存储库(ResourceRepository)。ResourceRepository用于访问和管理配置服务器上的静态资源,如配置文件、密钥等。
配置不同类型的ResourceRepository,如文件系统资源存储库或Git资源存储库。
通过REST接口提供资源访问和管理功能。
2.2.4. ConfigServerEncryptionConfiguration.class
ConfigServerEncryptionConfiguration 负责配置加密和解密功能。它提供加密和解密配置属性的能力,确保敏感数据在传输和存储时得到保护。
配置加密器(TextEncryptor),用于加密和解密敏感配置信息。
提供加密和解密端点,允许客户端通过API进行加密和解密操作。
2.2.5. ConfigServerMvcConfiguration.class
ConfigServerMvcConfiguration 配置Spring MVC相关的组件,为Spring Cloud Config Server提供RESTful API。它定义了Config Server的主要控制器和路由。
定义Config Server的REST API端点,处理配置属性的请求。
配置HTTP请求处理、路由和控制器。
2.2.6. ResourceEncryptorConfiguration.class
ResourceEncryptorConfiguration 负责配置与资源加密相关的功能。它确保资源存储库中的敏感数据在存储和访问时得到加密保护。
配置用于资源加密和解密的组件。
提供加密资源的支持,确保静态资源的安全性。
3. EnvironmentRepository
对于 Spring Cloud Config 而言,它把所有的配置信息抽象为一种 Environment(环境),而存储这些配置信息的地方就称为 EnvironmentRepository。
public interface EnvironmentRepository {Environment findOne(String application, String profile, String label);default Environment findOne(String application, String profile, String label, boolean includeOrigin) {return findOne(application, profile, label);}}
spring cloud中把配置信息抽象为application,profile和label三个维度来管理,即哪一个应用application在什么样的环境profile下,使用哪一个label的配置数据。
4. EnvironmentRepositoryConfiguration.class
这个类里加载很多的内容,包括svn、git、jdbc等等的RepositoryConfiguration。其中有一个Configuration类是DefaultRepositoryConfiguration.class。这个是放在最后一个加载的配置,即默认的配置:
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(value = EnvironmentRepository.class, search = SearchStrategy.CURRENT)
class DefaultRepositoryConfiguration {@Beanpublic MultipleJGitEnvironmentRepository defaultEnvironmentRepository(MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,MultipleJGitEnvironmentProperties environmentProperties) throws Exception {return gitEnvironmentRepositoryFactory.build(environmentProperties);}}
这里是加载MultipleJGitEnvironmentRepository的Bean,由gitEnvironmentRepositoryFactory的build方法来构建:
public MultipleJGitEnvironmentRepository build(MultipleJGitEnvironmentProperties environmentProperties)throws Exception {if (this.connectionFactory.isPresent()) {HttpTransport.setConnectionFactory(this.connectionFactory.get());this.connectionFactory.get().addConfiguration(environmentProperties);}MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment,environmentProperties, ObservationRegistry.NOOP);repository.setTransportConfigCallback(transportConfigCallbackFactory.build(environmentProperties));if (this.server.getDefaultLabel() != null) {repository.setDefaultLabel(this.server.getDefaultLabel());}repository.setGitCredentialsProviderFactory(gitCredentialsProviderFactory);repository.getRepos().forEach((name, repo) -> repo.setGitCredentialsProviderFactory(gitCredentialsProviderFactory));return repository;}
而DefaultRepositoryConfiguration这个类,被GitRepositoryConfiguration继承了。
@Configuration(proxyBeanMethods = false)
@Profile("git")
class GitRepositoryConfiguration extends DefaultRepositoryConfiguration {}
也就是说 Spring Cloud Config 中默认使用 Git 作为配置仓库来完成配置信息的存储和管理,提供的 EnvironmentRepository 就是 MultipleJGitEnvironmentRepository,而 MultipleJGitEnvironmentRepository 则继承了抽象类 JGitEnvironmentRepository。
当服务器启动时,在 JGitEnvironmentRepository 中会决定是否调用 initClonedRepository() 方法来完成从远程 Git 仓库 Clone 代码。如果执行了这一操作,相当于会将配置文件从 Git 上 clone 到本地,然后再进行其他的操作。在 JGitEnvironmentRepository 抽象类中,提供了大量针对第三方 Git 仓库的操作代码,无论采用诸如 Git、SVN 等具体某一种配置仓库的实现方式,最终我们处理的对象都是位于本地文件系统中的配置文件。

在AbstractScmEnvironmentRepository类中
@Overridepublic synchronized Environment findOne(String application, String profile, String label) {return findOne(application, profile, label, false);}@Overridepublic synchronized Environment findOne(String application, String profile, String label, boolean includeOrigin) {NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(),new NativeEnvironmentProperties(), this.observationRegistry);Locations locations = getLocations(application, profile, label);delegate.setSearchLocations(locations.getLocations());Environment result = delegate.findOne(application, profile, "", includeOrigin);result.setVersion(locations.getVersion());result.setLabel(label);return this.cleaner.clean(result, getWorkingDirectory().toURI().toString(), getUri());}
在上面的findOne方法中,调用了NativeEnvironmentRepository类的findOne方法:
@Overridepublic Environment findOne(String config, String profile, String label, boolean includeOrigin) {try {ConfigurableEnvironment environment = getEnvironment(config, profile, label);DefaultResourceLoader resourceLoader = new DefaultResourceLoader();Map<org.springframework.core.env.PropertySource<?>, PropertySourceConfigData> propertySourceToConfigData = new HashMap<>();ConfigDataEnvironmentPostProcessor.applyTo(environment, resourceLoader, null,StringUtils.commaDelimitedListToSet(profile), new ConfigDataEnvironmentUpdateListener() {@Overridepublic void onPropertySourceAdded(org.springframework.core.env.PropertySource<?> propertySource,ConfigDataLocation location, ConfigDataResource resource) {propertySourceToConfigData.put(propertySource,new PropertySourceConfigData(location, resource));}});environment.getPropertySources().remove("config-data-setup");return clean(ObservationEnvironmentRepositoryWrapper.wrap(this.observationRegistry, new PassthruEnvironmentRepository(environment)).findOne(config, profile, label, includeOrigin), propertySourceToConfigData);}catch (Exception e) {String msg = String.format("Could not construct context for config=%s profile=%s label=%s includeOrigin=%b",config, profile, label, includeOrigin);String completeMessage = NestedExceptionUtils.buildMessage(msg,NestedExceptionUtils.getMostSpecificCause(e));throw new FailedToConstructEnvironmentException(completeMessage, e);}}
我们看到最终委托 PassthruEnvironmentRepository 完成配置文件的读取,然后通过 clean 方法完成本地文件地址与远程仓库之间地址的转换。ConfigDataEnvironmentUpdateListener用于监听Environment的更新。
5. rest接口
Server端获取到了数据,是通过rest接口来提供给client的。这里EnvironmentController提供了rest接口:
@GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",produces = MediaType.APPLICATION_JSON_VALUE)public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) {return getEnvironment(name, profiles, null, false);}@GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",produces = EnvironmentMediaType.V2_JSON)public Environment defaultLabelIncludeOrigin(@PathVariable String name, @PathVariable String profiles) {return getEnvironment(name, profiles, null, true);}@GetMapping(path = "/{name}/{profiles}/{label:.*}", produces = MediaType.APPLICATION_JSON_VALUE)public Environment labelled(@PathVariable String name, @PathVariable String profiles, @PathVariable String label) {return getEnvironment(name, profiles, label, false);}@GetMapping(path = "/{name}/{profiles}/{label:.*}", produces = EnvironmentMediaType.V2_JSON)public Environment labelledIncludeOrigin(@PathVariable String name, @PathVariable String profiles,@PathVariable String label) {return getEnvironment(name, profiles, label, true);}
这里要注意path路径的配置,在类注解上有@RequestMapping(method = RequestMethod.GET, path = “${spring.cloud.config.server.prefix:}”)可以配置前缀,不配置的话就是默认值“”。
在方法上的路径,是/name/profile/label。这个正是配置文件中配置的内容。
相关文章:
spring cloud config server源码学习(一)
文章目录 1. 注解EnableConfigServer2. ConfigServerAutoConfiguration2.1 ConditionalOnBean和ConditionalOnProperty2.2 Import注解2.2.1. EnvironmentRepositoryConfiguration.class2.2.2. CompositeConfiguration.class2.2.3. ResourceRepositoryConfiguration.class2.2.4.…...
人脸识别——探索戴口罩对人脸识别算法的影响
1. 概述 人脸识别是一种机器学习技术,广泛应用于各种领域,包括出入境管制、电子设备安全登录、社区监控、学校考勤管理、工作场所考勤管理和刑事调查。然而,当 COVID-19 引发全球大流行时,戴口罩就成了日常生活中的必需品。广泛使…...
磁盘管理后续——盘符漂移问题解决
之前格式化磁盘安装了文件系统,且对磁盘做了相应的挂载,但是服务器重启后挂载信息可能有问题,或者出现盘符漂移、盘符变化、盘符错乱等故障,具体是dev/sda, sdb, sdc 等等在某些情况下会混乱掉 比如sda变成了sdb或者sdc变成了sdb等…...
基于GO 写的一款 GUI 工具,M3u8视频下载播放器-飞鸟视频助手
M3u8视频下载播放器-飞鸟视频助手 M3u8视频飞鸟视频助手使用m3u8下载m3u8 本地播放 软件下载地址m3u8嗅探 M3u8视频 M3u8视频格式是为网络视频播放设计,视频网站多数采用 m3u8格式。如腾讯,爱奇艺等网站。 m3u8和 mp4的区别: 一个 mp4是一个…...
关于EasyExcel导入数据时表格日期格式识别为数字问题
参考官方地址 自定义日期转字符串转换器 /*** 自定义excel日期转换器** author li* date 2024-05-29*/ public class CustomStringDateConverter implements Converter<String> {Overridepublic Class<?> supportJavaTypeKey() {return String.class;}Overridep…...
高通Android 12/13打开省电模式宏开关
1、添加到SettingsProvider配置项宏开关 默认节电助手自动开启百分比battery saver frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java private void loadGlobalSettings(SQLiteDatabase db) {在该方法中添加 ......final i…...
2023年西安交通大学校赛(E-雪中楼)
E.雪中楼 如果算出按南北的序列,再转成从低到高的编号序列,岂不是太麻烦了,幸好,没有在这方面费长时间,而是意识到,本质就是要从低到高的编号序列,所以我就按样例模拟了一下,当a[i]0…...
如何在vue2中使用tailwind
查看官方文档,不要去看过时的文章! 使用官网推荐的第一个安装方法 Installation - Tailwind CSS vue版本:2.6.10 1. 安装tailwind的包 npm install -D tailwindcss npx tailwindcss init 2. tailwind.config.js 文件中的content是你需要…...
【OrangePi AIpro】开箱初体验以及OAK深度相机测试
1. 简介 Orangepi AIPRO 是一款采用昇腾AI技术路线,集成4核64位处理器AI处理器的单板计算机,集成图形处理器,支持8TOPS AI算力,拥有8GB/16GB LPDDR4X,可以外接eMMC模块,支持双4K高清输出。 Orange Pi AIpr…...
滑动窗口模板(Java)
题目描述 有一个长为 𝑛 的序列 𝑎,以及一个大小为 𝑘 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。 例如,对于序列 [1,3,−1,−3,5,3,6,7] …...
transformers.BertTokenizer入门使用
教程link 示例代码 from transformers import OpenAIGPTLMHeadModel, GPT2LMHeadModel, BertTokenizer import torch tokenizer BertTokenizer.from_pretrained("thu-coai/CDial-GPT_LCCC-large") model OpenAIGPTLMHeadModel.from_pretrained("thu-coai/CD…...
快乐数-力扣
使用一个set来存储遇到的每个数,如果遇到的数在set中,那么说明这个数不是快乐数,否则一直循环下去,直到n 1结束循环,表示这个数是个快乐数。 需要注意的是,给定一个数 n, 怎样对这个数 n 进行每一位求和。…...
Git标签的使用
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
【uni-app】Pinia 持久化
小程序端 Pinia 持久化 说明:Pinia 用法与 Vue3 项目完全一致,uni-app 项目仅需解决持久化插件兼容性问题。 持久化存储插件 安装持久化存储插件: pinia-plugin-persistedstate pnpm i pinia-plugin-persistedstate插件默认使用 localStor…...
Flink 窗口
窗口(Window) 窗口是处理无限流的核心。 窗口将流分割成有限大小的“桶”,我们可以计算窗口中的数据。 窗口程序一般有键控流(keyed streams)的窗口程序 和 非键控流(non-keyed streams)的窗口…...
基于大模型和RAG技术实现的开源项目
基于大模型和RAG技术实现的开源项目 为解决大模型的不足,使用RAG技术增强大模型生成内容的针对性和可读性能力,有很多不错的开源项目。例如下面的项目。 1 ragflow 优点:可以对文档和知识库进行管理,构建不同的知识库ÿ…...
mac m1安装homebrew管理工具(brew命令)完整流程
背景 因为mac上的brew很久没用了,版本非常旧,随着mac os的更新,本机的homebrew大部分的功能都无法使用,幸好过去通过brew安装的工具比较少,于是决定重新安装一遍brew。 卸载旧版brew 法一:通过使用线上…...
Liunx学习随笔
Linux学习随笔 Linux学习随笔一.前期准备1.安装Vmware Workstation软件2.下载linux镜像3.安装操作系统4.配置静态ip5.下载安装远程连接工具 二.语法2.1 linux哲学思想(原则)2.2 小命令 夕阳无限好,只是近黄昏,时隔一年,重新提笔 没有比脚更远…...
mac中文件夹怎么显示.git隐藏文件
1. 打开终端应用程序,然后进入到包含.git文件夹的目录,可以使用以下命令来显示隐藏文件和文件夹: defaults write com.apple.finder AppleShowAllFiles YES 2. 然后重启 Finder: killall Finder...
【PB案例学习笔记】-13 徒手做个电子时钟
写在前面 这是PB案例学习笔记系列文章的第11篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gite…...
GDBFrontend表达式求值器深度解析:多窗口实时变量监控技巧
GDBFrontend表达式求值器深度解析:多窗口实时变量监控技巧 【免费下载链接】gdb-frontend ☕ GDBFrontend is an easy, flexible and extensible gui debugger. Try it on https://debugme.dev 项目地址: https://gitcode.com/gh_mirrors/gd/gdb-frontend GD…...
来自硅谷的顶级外卖-Claude Code 源码泄露事件讨论
Claude Code 源码泄露事件全解析摘要:2026年3月,Anthropic 旗下 AI 编程工具 Claude Code 的完整源码被人通过匿名渠道公开。这次泄露撕开了这款"明星产品"的外衣——5层模块架构、20安全验证器、自研 Ink 渲染引擎、四层记忆系统。代码里没有…...
Llama-3.2V-11B-cot开源大模型案例:科研论文插图数据真实性初筛
Llama-3.2V-11B-cot开源大模型案例:科研论文插图数据真实性初筛 1. 项目背景与价值 科研论文插图的真实性核查是学术出版领域的重要环节。传统人工检查方式存在效率低、主观性强等问题。Llama-3.2V-11B-cot多模态大模型为解决这一问题提供了创新方案。 这款基于M…...
2026年正点原子开发板移植方案——从0开始的Rootfs之路(5)WSL + NFS 网络启动踩坑记:从挂载失败到成功启动的完整历程
2026年正点原子开发板移植方案——从0开始的Rootfs之路(5)WSL NFS 网络启动踩坑记:从挂载失败到成功启动的完整历程项目已经开源!尝试使用IMX-Forge给你的开发板跑新的Linux 7.0内核:https://github.com/Awesome-Embe…...
PDF智能解析新选择:GLM-OCR支持表格/公式识别,效果惊艳
PDF智能解析新选择:GLM-OCR支持表格/公式识别,效果惊艳 1. 为什么需要新一代OCR技术 在日常办公和学术研究中,PDF文档处理一直是个令人头疼的问题。传统OCR工具在面对复杂版式、嵌套表格或数学公式时,往往表现不佳。想象一下这样…...
PyTorch实战:从零构建支持向量机进行图像二分类
1. 支持向量机与图像分类的奇妙碰撞 第一次听说要用支持向量机(SVM)做图像分类时,我脑子里立刻浮现出两个问号:这个传统机器学习算法能处理图像数据吗?为什么要用PyTorch实现而不是直接用scikit-learn?直到亲手实现了整个流程&…...
GLM-4.1V-9B-Base保姆级教学:Web界面截图+问题输入框最佳实践
GLM-4.1V-9B-Base保姆级教学:Web界面截图问题输入框最佳实践 1. 认识GLM-4.1V-9B-Base GLM-4.1V-9B-Base是智谱开源的视觉多模态理解模型,专门用于处理图像内容识别、场景描述、目标问答和中文视觉理解任务。这个模型已经完成了Web化封装,可…...
多模态Agent架构实战落地:从需求分析到生产部署
多模态Agent架构实战落地:从需求分析到生产部署 随着大语言模型技术的普及,单一文本交互的智能系统已无法满足复杂业务场景需求——电商平台需要同时理解用户的商品描述文本、实拍图片和售后语音诉求,教育场景需要处理手写作业、视频讲解和文…...
Qwen2.5-0.5B-Instruct新手入门:从零到一的AI助手搭建全流程
Qwen2.5-0.5B-Instruct新手入门:从零到一的AI助手搭建全流程 1. 认识Qwen2.5-0.5B-Instruct 1.1 模型特点与优势 Qwen2.5-0.5B-Instruct是阿里开源的通义千问系列中最轻量级的指令微调版本,专为资源有限环境优化设计。这个5.08亿参数的模型虽然体积小…...
LFM2.5-1.2B-Thinking-GGUF部署教程:Ubuntu/CentOS/Debian三平台通用安装步骤
LFM2.5-1.2B-Thinking-GGUF部署教程:Ubuntu/CentOS/Debian三平台通用安装步骤 1. 平台简介 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,特别适合在资源有限的环境中快速部署。该镜像内置了GGUF模型文件和llama.cpp运行时ÿ…...
