【Spring Boot 源码学习】初识 ConfigurableEnvironment
《Spring Boot 源码学习系列》

初识 ConfigurableEnvironment
- 一、引言
- 二、主要内容
- 2.1 Environment
- 2.1.1 配置文件(profiles)
- 2.1.2 属性(properties)
- 2.2 ConfigurablePropertyResolver
- 2.2.1 属性类型转换配置
- 2.2.2 占位符配置
- 2.2.3 值分隔符配置
- 2.2.4 必需属性验证配置
- 2.3 ConfigurableEnvironment
- 2.3.1 接口方法
- 2.3.2 具体实现
- 三、总结
一、引言
上篇博文,Huazie 带大家深入分析下 ApplicationArguments 接口及其默认实现。在初始化完 ApplicationArguments 之后,Spring Boot 就开始通过 prepareEnvironment 方法对 ConfigurableEnvironment 对象进行初始化操作。在介绍 ConfigurableEnvironment 的初始化之前,我们有必要先认识一下 ConfigurableEnvironment 接口。

二、主要内容
注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。
下面贴出 ConfigurableEnvironment 的源码:
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {void setActiveProfiles(String... profiles);void addActiveProfile(String profile);void setDefaultProfiles(String... profiles);MutablePropertySources getPropertySources();Map<String, Object> getSystemProperties();Map<String, Object> getSystemEnvironment();void merge(ConfigurableEnvironment parent);
}
从上述源码,可以看出 ConfigurableEnvironment 接口继承了 Environment 和 ConfigurablePropertyResolver 接口,它们其实最终都继承自 PropertyResolver 接口。
2.1 Environment

org.springframework.core.env.Environment 表示当前应用程序在其中运行的环境。它模拟了应用程序环境的两个关键方面:
2.1.1 配置文件(profiles)
Profile 是一个命名的、逻辑上的 bean 定义组,这些定义只有在给定的配置文件处于活动状态时才会被注册到容器中。通过 Environment 可以确定哪些配置文件(如果有)当前是活动的,以及哪些配置文件(如果有)应该默认是活动的。可以使用 @Profile 注解来指定 bean 应该在哪个配置文件下被注册。
2.1.2 属性(properties)
属性有各种来源,如属性文件、JVM 系统属性、系统环境变量、JNDI、servlet 上下文参数、临时的 Properties 对象、Map 等。Environment 对象为用户提供了一个方便的服务接口,用于配置属性源并从这些源中解析属性。通过 Environment,可以方便地访问和解析这些属性,而无需直接操作这些源。
此外,Environment 接口还继承了 PropertyResolver 接口【用于根据任何底层源解析属性的接口】,这意味着它还提供了与属性访问相关的功能。
2.2 ConfigurablePropertyResolver

org.springframework.core.env.ConfigurablePropertyResolver 也继承了 PropertyResolver 接口,并在其基础上增加了更多的配置选项:
2.2.1 属性类型转换配置
ConfigurablePropertyResolver 提供了基于 org.springframework.core.convert.ConversionService 的属性类型转换功能。ConversionService 是 Spring 中用于类型转换的接口,它允许将一种类型的对象转换为另一种类型的对象。
与之关联的方法如下:
getConversionService(): 获取当前用于类型转换的ConfigurableConversionService实例。setConversionService(ConfigurableConversionService conversionService): 设置用于类型转换的ConfigurableConversionService实例。这允许用户自定义类型转换的逻辑,以满足特定的应用程序需求。
2.2.2 占位符配置
ConfigurablePropertyResolver 允许开发者配置占位符的前缀和后缀。默认情况下,前缀是 ${,后缀是 }。占位符的值本身也可以包含其他占位符,形成嵌套占位符,ConfigurablePropertyResolver 支持嵌套占位符的解析。
与之相关的方法如下:
setPlaceholderPrefix(String placeholderPrefix): 设置占位符的前缀。在解析属性时,这些前缀将被用来识别需要替换的占位符。setPlaceholderSuffix(String placeholderSuffix): 设置占位符的后缀。与前缀一起,它们定义了占位符的完整格式。setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders): 设置是否忽略无法解析的嵌套占位符。如果设置为true,则当遇到无法解析的嵌套占位符时,解析器将不会抛出异常,而是继续执行。
2.2.3 值分隔符配置
值分隔符是指在解析属性值时,用于分隔占位符与其关联默认值的字符设置。
比如,在配置文件中有这样的属性值:${propertyName:defaultValue}。
在这里 propertyName 是占位符,而 defaultValue 是在 propertyName 无法解析时使用的默认值。那显然在上述示例中,: 就是 值分隔符。
与之相关的方法如下:
setValueSeparator(@Nullable String valueSeparator): 设置值分隔符。在某些情况下,属性值可能包含多个值,这些值由分隔符分隔。此方法允许用户指定分隔符。
2.2.4 必需属性验证配置
必需属性验证配置是 Spring 框架中用于确保应用程序配置中包含某些关键属性的一种机制。
与之相关的方法如下:
setRequiredProperties(String... requiredProperties): 设置必需的属性。这些属性必须在解析过程中存在,否则验证将失败。validateRequiredProperties() throws MissingRequiredPropertiesException: 验证是否所有必需的属性都已设置。如果任何必需属性缺失,此方法将抛出MissingRequiredPropertiesException异常。
2.3 ConfigurableEnvironment
了解了 Environment 和 ConfigurablePropertyResolver,我们再来看看 ConfigurableEnvironment 。
2.3.1 接口方法
ConfigurableEnvironment 代表了一个可配置的环境,其定义了如下的方法:
setActiveProfiles(String... profiles):设置当前激活的Profile组集合。在Spring 中,Profile允许用户根据特定的环境(如开发、测试、生产)加载不同的配置。通过传递一个或多个Profile名称作为参数,你可以激活这些Profile。addActiveProfile(String profile):向当前激活的Profile组集合中添加一个Profile组。setDefaultProfiles(String... profiles):设置默认激活的Profile组集合。激活的Profile组集合为空时,会默认实用默认的Profile组集合。getPropertySources():返回当前环境的MutablePropertySources对象。PropertySources是一个包含多个PropertySource的列表,每个PropertySource都可以提供属性。MutablePropertySources允许你添加、替换或删除PropertySource。getSystemProperties():返回 Java 系统属性的映射。这些属性是 JVM 启动时通过-D参数或在代码中使用System.setProperty(key, value)进行设置。getSystemEnvironment():返回操作系统环境变量的映射。这些变量通常包含关于系统配置和运行时的信息。merge(ConfigurableEnvironment parent):将父ConfigurableEnvironment的属性源合并到当前环境中。合并时,父环境的属性源将添加到当前环境的属性源列表的开头,从而允许它们覆盖当前环境的任何同名属性。
2.3.2 具体实现
org.springframework.core.env.AbstractEnvironment 是一个抽象类,实现了 ConfigurableEnvironment 接口,为环境配置(如属性源和 Profile 文件管理)提供了基本的支持。
org.springframework.core.env.StandardEnvironment 继承自 AbstractEnvironment,应用于非 Web 环境。它是 Spring 中默认的环境配置类,负责读取系统属性、环境变量以及配置文件中的配置信息,并将其封装在一个 PropertySources 对象中供 Spring 应用程序使用。
org.springframework.web.context.support.StandardServletEnvironment 继承自 StandardEnvironment,它是基于 Servlet 的 Web 应用程序要使用的 Environment 实现。所有基于 Servlet 的 Web 相关的 ApplicationContext 类都会默认初始化一个实例。提供 ServletConfig、ServletContext 和基于 JNDI 的 PropertySource 实例。在初始化过程中,会根据 ServletContext 和 ServletConfig 的可用性来初始化和配置属性源。通过 customizePropertySources() 方法,可以自定义属性源的添加顺序和配置方式。
org.springframework.mock.env.MockEnvironment 继承自 AbstractEnvironment,它用于测试目的,可以模拟环境变量和系统属性的值。
三、总结
本篇博文 Huazie 同大家一起了解了 ConfigurableEnvironment 接口和其父接口,这些对于后续理解 ConfigurableEnvironment 的初始化操作至关重要。接下来的博文将会继续聚焦 Spring Boot 启动运行阶段,敬请期待!!!
相关文章:
【Spring Boot 源码学习】初识 ConfigurableEnvironment
《Spring Boot 源码学习系列》 初识 ConfigurableEnvironment 一、引言二、主要内容2.1 Environment2.1.1 配置文件(profiles)2.1.2 属性(properties) 2.2 ConfigurablePropertyResolver2.2.1 属性类型转换配置2.2.2 占位符配置2.…...
开关电源中强制连续FCCM模式与轻载高效PSM,PFM模式优缺点对比笔记
文章目录 前言一、连续FCCM模式优点:缺点: 二,轻载高效PSM,PFM优点:缺点: 总结 前言 今天我们来学习下开关电源中,强制连续FCCM模式与轻载高效PSM,PFM模式优缺点对比 一、连续FCCM模式 优点: …...
5分钟教你用AI把老照片动起来,别再去花49块9的冤枉钱了
文章目录 需要的工具 最近,AI视频在各大平台上,又火了。 只是火的形式,变成了将老照片动起来,打情感牌,或者做很多经典电视剧的再整活。 直接把可灵的生成时间,从以前的4分钟,生生的干成了20分钟…...
Ruby 环境变量
Ruby 环境变量 概述 环境变量在编程中扮演着重要的角色,尤其是在Ruby这样的动态编程语言中。它们是操作系统用来存储有关其操作环境的信息的变量,可以在程序运行时影响其行为。Ruby程序可以通过环境变量来获取配置信息、系统细节或用户特定的设置。本文将深入探讨Ruby中环境…...
BPF:BCC工具 funccount 统计内核函数调用(内核函数、跟踪点USDT探针)认知
写在前面 博文内容涉及BCC工具 funccount 认知funccount 可以帮助用户追踪和分析Linux系统上特定函数、系统探针或USDT探针的运行次数。这对于性能分析、故障排查和系统优化等场景非常有用。理解不足小伙伴帮忙指正 😃,生活加油 不必太纠结于当下,也不必…...
DPO算法推导
DPO 核心思想:直接使用偏好数据进行策略优化,省去 reward 模型策略优化。 技术背景知识: 首先给定prompt x,生成两个答案 ( y 1 , y 2 ) Π S F T ( y ∣ x ) (y_1,y_2)~\Pi^{SFT}(y|x) (y1,y2) ΠSFT(y∣x) ,并通…...
Qt源码分析:窗体绘制与响应
作为一套开源跨平台的UI代码库,窗体绘制与响应自然是最为基本的功能。在前面的博文中,已就Qt中的元对象系统(反射机制)、事件循环等基础内容进行了分析,并捎带阐述了窗体响应相关的内容。因此,本文着重分析Qt中窗体绘制相关的内容…...
docker 安装 禅道
docker pull hub.zentao.net/app/zentao:20.1.1 sudo docker network create --subnet172.172.172.0/24 zentaonet 使用 8087端口号访问 使用禅道mysql 映射到3307 sudo docker run \ --name zentao2 \ -p 8087:80 \ -p 3307:3306 \ --networkzentaonet \ --ip 172.172.172.…...
【简要说说】make 增量编译的原理
make 增量编译的原理 make是一个工具,它可以根据依赖关系和时间戳来自动执行编译命令。 当您修改了源代码文件后,make会检查它们的修改时间是否比目标文件(如可执行文件或目标文件)新,如果是,就会重新编译…...
DETRs Beat YOLOs on Real-time Object Detection论文翻译
cvpr 2024 论文名称 DETRs在实时目标检测上击败YOLO 地址 https://arxiv.longhoe.net/abs/2304.08069 代码 https://github.com/lyuwenyu/RT-DETR 目录 摘要 1介绍 2.相关工作 2.1实时目标探测器 2.2.端到端物体探测器 3.检测器的端到端速度 3.1.NMS分析 3.2.端到端速度…...
SpringBoot 多数据源配置
目录 一. 引入maven依赖包 二. 配置yml 三、创建 xml 分组文件 四、切换数据源 一. 引入maven依赖包 <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.6.1&…...
RK3568驱动指南|第十六篇 SPI-第192章 mcp2515驱动编写:完善write和read函数
瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…...
#BI建模与数仓建模有什么区别?指标体系由谁来搭建?
问题1: 指标体系是我们数仓来搭建还是分析师来做,如何去推动? 问题2:BI建模与数仓建模有什么区别? 指标体系要想做好,其实是分两块内容的,一块是顶层设计阶段,业务指标体系的搭建&am…...
如何用Python实现三维可视化?
Python拥有很多优秀的三维图像可视化工具,主要基于图形处理库WebGL、OpenGL或者VTK。 这些工具主要用于大规模空间标量数据、向量场数据、张量场数据等等的可视化,实际运用场景主要在海洋大气建模、飞机模型设计、桥梁设计、电磁场分析等等。 本文简单…...
chrome.storage.local.set 未生效
之前chrome.storage.local.set 和 get 一直不起作用 使用以下代码运行成功。 chrome.storage.local.set({ pageState: "main" }).then(() > {console.log("Value is set");});chrome.storage.local.get(["pageState"]).then((result) > …...
泛微开发修炼之旅--30 linux-Ecology服务器运维脚本
文章链接:30 linux-ecology服务器运维脚本...
LeetCode 全排列
思路:这是一道暴力搜索问题,我们需要列出答案的所有可能组合。 题目给我们一个数组,我们很容易想到的做法是将数组中的元素进行排列,如何区分已选中和未选中的元素,容易想到的是建立一个标记数组,已经选中的…...
python实现支付宝异步回调验签
说明 python实现支付宝异步回调验签,示例中使用Django框架。 此方案使用了支付宝的pythonSDK,请一定装最新版本的,支付宝官网文档不知道多久没更新了,之前的版本pip安装会报一些c库不存在的错误; pip install alipay-…...
注意!Vue.js 或 Nuxt.js 中请停止使用.value
大家好,我是CodeQi! 一位热衷于技术分享的码仔。 当您在代码中使用.value时,必须每次都检查变量是否存在并且是引用。 这可能很麻烦,因为在运行时使用.value可能会导致错误。然而,有一个简单的解决方法,即使用unref()而不是.value。 unref()会检查变量是否是引用,并自…...
Java:JDK、JRE和JVM 三者关系
文章目录 一、JDK是什么二、JRE是什么三、JDK、JRE和JVM的关系 一、JDK是什么 JDK(Java Development Kit):Java开发工具包 JRE:Java运行时环境开发工具:javac(编译工具)、java(运行…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
