【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(运行…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
