Spring Boot环境配置Envirnoment

Srping Boot 中我们使用 EnvironmentAware 注入 Environment 对象后,可以在 Environment 中获得系统参数,命令行采参数,文件配置等信息。

Environment 是如何存储,管理这些值的呢?变量发生冲突怎么办呢?我们可以扩展 Environment 的行为吗?本文结合 Spring Boot 启动时 Environment 的初始化过程,了解 Environment 的配置方式、优先级、配置源与扩展方式。

Spring 中的 Environment 指什么?

Spring 中的 Environment 是什么呢?了解 Environment 之前,不得不提到 Property 和 Profile。

我们在写项目的时候,经常会抽取一些配置项,在 Java 中通常叫做属性,也就是 Property,本质是一组键值对配置信息。使用配置项的好处在于修改起来很容易,只需修改下配置文件或命令行参数,然后重启一下就可以了。

开发过程中,大多数项目都有多套配置对应多个环境,一般来说有开发环境、测试环境和生产环境。这里的“环境”就叫做 Profile。程序可以读取到 Profile 的值,根据 Profile 的不同展示不同的特性。其实从本质上讲,“环境”也是一个“配置”,只是这个配置太重要了,也比较特殊,所以作为一个单独的概念来处理。

Environment = Property + Profile

Spring Boot 中,默认使用的 Environment 的实现类是 StandardServletEnvironment,我们可以通过它的类图了解 Spring Boot 中的 Environment 是如何管理的。

PropertyResolver 接口负责 Property 的获取(通过 key 获得 value),Environment 继承了这个接口,加入获得 Profile 的内容。ConfigurablePropertyResolver 继承了 PropertyResolver,为了解决 Property 的获取过程中涉及到的数据类型的转换和${…}表达式的解析问题。ConfigurableEnvironment 在此基础上,加入了 Profile 的设置功能。ConfigurableWebEnvironment 扩展了 web 功能,将 servlet 上下文作为配置源。

AbstractEnvironment,StandardEnvironment,StandardServletEnvironment 都是 Spring 对上述功能的实现。

Spring Boot 中的配置来自哪里?

Spring Boot 中的配置来自不同的地方,最常见的来自于 application.properties、application.yaml、环境变量和命令行参数。我们可以在 Spring Boot 的官方文档看到各种各样的配置方式。

官方一共给出了 14 中配置方式,并且给出了配置的优先级。数字越大优先级越高。

  • 通过硬编码的方式(SpringApplication.setDefaultProperties)进行配置。
  • 在 Spring Boot 的配置类上使用 @PropertySource 注解指定配置文件。
  • 使用配置文件 (比如 application.properties 文件)。
  • 通过 random.* 配置的随机属性。
  • 操作系统中的环境变量。
  • Java 的系统属性,可通过 System.getProperties() 获得相关内容。
  • java:comp/env 中 JNDI 属性。
  • ServletContext 初始化参数(web 环境)
  • ServletConfig 初始化参数(web 环境)
  • SPRING_APPLICATION_JSON 属性,该属性以 JSON 形式存储在系统环境变量中。
  • 命令行参数,类似于 java -jar -Denv=DEV 之类。
  • @SpringBootTest 注解,仅在测试中使用。
  • @TestPropertySource 注解,仅在测试中使用。
  • 激活 devtools 时,位于 $HOME/.config/spring-boot 下的配置。

如此之多的配置方式,且配置项的来源是多样化的,如何对用户暴露这些配置呢?一种方式就是将所有来源都暴露给用户,用户可以从任意配置源中获得配置。还有一种方式就是由 Spring 管理这些配置源,内部排好优先级,对外暴露统一的 get 方法,用户不需要知道其中的细节。Spring 显然使用了后者。

Spring 使用 PropertySource 来表示一个配置源,PropertySource 有很多子类,比如 SystemEnvironmentPropertySource,PropertiesPropertySource 等等。Spring 将这些 PropertySource 维护在一个列表中,当用户想要获得一个配置的时候,Spring 会遍历这些配置源,依次判断是否有匹配的配置。配置源在列表中的数据其实就代表了优先级。

如下是 Spring 从 propertySources 中获得 Property 的方式。

protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {if (this.propertySources != null) {for (PropertySource<?> propertySource : this.propertySources) {Object value = propertySource.getProperty(key);if (value != null) {if (resolveNestedPlaceholders && value instanceof String) {value = resolveNestedPlaceholders((String) value);}logKeyFound(key, propertySource, value);return convertValueIfNecessary(value, targetValueType);}}}return null;
}

综上,Spring Boot 中的 Environment 中维护了若干个 PropertySource,也就是配置源,所有的配置到来自于这些配置源。

java 通过System.getProperties()获取系统参数

java.version Java 运行时环境版本

java.vendor Java 运行时环境供应商

java.vendor.url Java 供应商的 URL

java.home Java 安装目录

java.vm.specification.version Java 虚拟机规范版本

java.vm.specification.vendor Java 虚拟机规范供应商

java.vm.specification.name Java 虚拟机规范名称

java.vm.version Java 虚拟机实现版本

java.vm.vendor Java 虚拟机实现供应商

java.vm.name Java 虚拟机实现名称

java.specification.version Java 运行时环境规范版本

java.specification.vendor Java 运行时环境规范供应商

java.specification.name Java 运行时环境规范名称

java.class.version Java 类格式版本号

java.class.path Java 类路径

java.library.path 加载库时搜索的路径列表

java.io.tmpdir 默认的临时文件路径

java.compiler 要使用的 JIT 编译器的名称

java.ext.dirs 一个或多个扩展目录的路径

os.name 操作系统的名称

os.arch 操作系统的架构

os.version 操作系统的版本

file.separator 文件分隔符(在 UNIX 系统中是“/”)

path.separator 路径分隔符(在 UNIX 系统中是“:”)

line.separator 行分隔符(在 UNIX 系统中是“/n”)

user.name 用户的账户名称

user.home 用户的主目录

user.dir 用户的当前工作目录

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

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

相关文章

Python生成exe文件运行出现黑框闪退如何查看运行bug?

cmd进行回车 第一&#xff1a;进入到可执行exe文件目录&#xff0c;如下图所示 第二&#xff1a;输入可执行文件名&#xff0c;然后就会出现报错提示

Java开发 - 深入理解Redis哨兵机制原理

前言 Redis的主从、哨兵模式、集群模式&#xff0c;在前文中都已经有了详细的搭建流程&#xff0c;可谓是手把手教程&#xff0c;也得到了很多朋友的喜欢。由于前文偏向于应用方面&#xff0c;就导致了理论知识的匮乏&#xff0c;我们可能会用了&#xff0c;但却不明所以&…

自定义实现list及其功能

#pragma once #include <iostream> #include <assert.h> using namespace std;namespace test {//******************************设置结点******************************template<class T>struct list_node{T _data;list_node<T>* _next;list_node&l…

ES6 Generator和Promise

目录 Generator 如何创建Generator函数 ? 模拟发起异步请求 Promise 实例化 实例方法 工厂函数 静态方法 Promise.all([p1,p2,....]) Promise.race([p1,p2,....]) Promise.any([p1,p2,....]) Promise.allSettled([p1,p2,....]) Generator Generator是ES6提供的一种…

云计算与大数据——MPI集群配置

什么是MPI集群&#xff1f; MPI&#xff08;消息传递接口&#xff09;是一种用于编写并行程序的标准&#xff0c;它允许在多个计算节点上进行通信和协作。MPI集群配置是指在一个或多个计算节点上设置MPI环境以实现并行计算。 MPI集群配置的步骤&#xff1a; 硬件选型&#x…

C++--day3(内联函数、结构体、类、封装、this、构造函数、析构函数)

#include <iostream>using namespace std;class My_stack { private:int *ptr; //指向堆区空间int top; //记录栈顶元素int size; public://有参构造My_stack(int size):ptr(new int[size]),top(-1){this->sizesize;cout<<"My_stack::有参构造&…

Django MultiValueDictKeyError 表单数据用request.POST 非表单数据用request.body

表单数据&#xff1a;Content-Type(请求头)为application/x-www-form-urlencoded的数据。 用request.POST获取 a request.POST.get(a) a request.POST[a] alist request.POST.getlist(a) 非表单数据&#xff1a;Content-Type(请求头)为非application/x-www-form-urlenco…

2023年郑州/杭州/深圳CSPM-3中级国标项目管理认证招生

CSPM-3中级项目管理专业人员认证&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…

【动态内存错误详解和C的内存分区】

常见的动态内存错误 1.动态内存错误2.经典案例分析2.1案例一2.1.1**问题分析**2.1.2**修改错误** 2.2案例二2.2.1 原因分析2.2.2 解决问题 c/c内存分布1.2 内存分区简介1.2.1 栈区(stack)1.2.2 堆区(heap)1.2.3 全局(静态)区1.2.4 常量区1.2.5 代码区 1.动态内存错误 &#xf…

Argo CD 入门扫盲使用

目录 一、什么是 argo cd 二、为什么使用 argo cd 三、argo cd 架构图 四、Argo CD 使用 1、安装 Argo CD 2、安装 Argo CD CLI 3、发布 Argo CD 服务 4、获取 Argo CD 密码 5、准备 Git 仓库 6、创建 Argo CD App 7、版本升级 8、版本回滚 一、什么是 argo cd A…

STM32学习笔记(十三)丨USART通用同步/异步收发器(串口外设的基本使用丨串口发送数据、串口发送+接收数据)

本篇文章包含的内容 一、STM32的USART外设1.1 STM32的USAER外设简介1.2 USART外设的结构和工作原理1.3 串口通信数据帧1.4 起始位侦测和USART的噪声判断机制1.5 波特率发生器 二、串口发送和接收数据包2.1 HEX数据包2.2 文本数据包2.3 固定包长HEX数据包接收2.4 可变包长文本数…

简单认识MySQL数据库日志和数据的备份恢复

文章目录 Mysql 备份与还原一、数据备份的重要性二、数据库备份类型1 、物理备份2 、逻辑备份 三、常见的备份方法1、 物理冷备2、 专用备份工具 mysqldump 或 mysqlhotcopy3、 启用二进制日志进行增量备份3.4 第三方工具备份 四、MySQL完全备份1、简介2、优点&#xff1a;3、缺…