当前位置: 首页 > news >正文

【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 接口继承了 EnvironmentConfigurablePropertyResolver 接口,它们其实最终都继承自 PropertyResolver 接口。

2.1 Environment

在这里插入图片描述

org.springframework.core.env.Environment 表示当前应用程序在其中运行的环境。它模拟了应用程序环境的两个关键方面:

2.1.1 配置文件(profiles)

Profile 是一个命名的、逻辑上的 bean 定义组,这些定义只有在给定的配置文件处于活动状态时才会被注册到容器中。通过 Environment 可以确定哪些配置文件(如果有)当前是活动的,以及哪些配置文件(如果有)应该默认是活动的。可以使用 @Profile 注解来指定 bean 应该在哪个配置文件下被注册。

2.1.2 属性(properties)

属性有各种来源,如属性文件JVM 系统属性系统环境变量JNDIservlet 上下文参数临时的 Properties 对象Map 等。Environment 对象为用户提供了一个方便的服务接口,用于配置属性源并从这些源中解析属性。通过 Environment,可以方便地访问和解析这些属性,而无需直接操作这些源。

此外,Environment 接口还继承了 PropertyResolver 接口【用于根据任何底层源解析属性的接口】,这意味着它还提供了与属性访问相关的功能。

2.2 ConfigurablePropertyResolver

在这里插入图片描述

org.springframework.core.env.ConfigurablePropertyResolver 也继承了 PropertyResolver 接口,并在其基础上增加了更多的配置选项:

2.2.1 属性类型转换配置

ConfigurablePropertyResolver 提供了基于 org.springframework.core.convert.ConversionService 的属性类型转换功能。ConversionServiceSpring 中用于类型转换的接口,它允许将一种类型的对象转换为另一种类型的对象。

与之关联的方法如下:

  • 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

了解了 EnvironmentConfigurablePropertyResolver,我们再来看看 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,它是基于 ServletWeb 应用程序要使用的 Environment 实现。所有基于 ServletWeb 相关的 ApplicationContext 类都会默认初始化一个实例。提供 ServletConfigServletContext 和基于 JNDIPropertySource 实例。在初始化过程中,会根据 ServletContextServletConfig 的可用性来初始化和配置属性源。通过 customizePropertySources() 方法,可以自定义属性源的添加顺序和配置方式。

org.springframework.mock.env.MockEnvironment 继承自 AbstractEnvironment,它用于测试目的,可以模拟环境变量和系统属性的值。

三、总结

本篇博文 Huazie 同大家一起了解了 ConfigurableEnvironment 接口和其父接口,这些对于后续理解 ConfigurableEnvironment 的初始化操作至关重要。接下来的博文将会继续聚焦 Spring Boot 启动运行阶段,敬请期待!!!

相关文章:

  • 数据结构(3.8)——栈的应用
  • gdb调试命令大全
  • 【产品经理】订单处理11-订单修改场景梳理
  • 泛微开发修炼之旅--29用计划任务定时发送邮件提醒
  • RISC-V在当前计算架构中的地位
  • 使用Vue CLI方式创建Vue3.0应用程序
  • 如何在Java项目中实现领域驱动设计(DDD)
  • 2024华为OD机试真题-找数字-(C++/Python)-C卷D卷-200分
  • 【BUUCTF-PWN】7-[第五空间2019 决赛]PWN5
  • 【大模型LLM面试合集】大语言模型基础_激活函数
  • 金斗云 HKMP智慧商业软件 任意用户创建漏洞复现
  • 《Windows API每日一练》6.2 客户区鼠标消息
  • 【Java09】方法(下)
  • 免费办公软件 -- LibreOffice v24.2.4
  • 2024 年最佳 Figma 字体
  • 分享的文章《人生如棋》
  • DataBase in Android
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • happypack两次报错的问题
  • Java的Interrupt与线程中断
  • JAVA多线程机制解析-volatilesynchronized
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 给github项目添加CI badge
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 如何解决微信端直接跳WAP端
  • 深度学习在携程攻略社区的应用
  • 思否第一天
  • 写代码的正确姿势
  • 一起参Ember.js讨论、问答社区。
  • ​Java基础复习笔记 第16章:网络编程
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # .NET Framework中使用命名管道进行进程间通信
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • #php的pecl工具#
  • (4)STL算法之比较
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (四)汇编语言——简单程序
  • (译)计算距离、方位和更多经纬度之间的点
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .net 后台导出excel ,word
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?