Spring源码:Spring运行环境Environment

news/2024/5/19 9:18:49

Spring运行环境

Spring在创建容器时,会创建Environment环境对象,用于保存spring应用程序的运行环境相关的信息。在创建环境时,需要创建属性源属性解析器,会解析属性值中的占位符,并进行替换。

创建环境时,会通过System.getProperties()获取JVM系统属性,会通过System.getenv()获取JVM环境属性。

Environment在Spring中的使用

spring在创建容器时需要指定需要加载配置文件路径,在加载配置文件路径时,需要解析字符串中的占位符。解析占位符时,需要环境信息,此时会创建一个标准的spring运行环境,即创建StandardEnvironment对象。
1、调用setConfigLocations方法给spring设置需要加载的配置文件的路径,源码如下:

// 将配置文件的路径放到configLocations 字符串数组中
public void setConfigLocations(@Nullable String... locations) {if (locations != null) {Assert.noNullElements(locations, "Config locations must not be null");// 设置了几个配置文件,就创一个多长的字符串数组,用来存放配置文件的路径this.configLocations = new String[locations.length];for (int i = 0; i < locations.length; i++) {//解析路径,将解析的路径存放到字符串数组中this.configLocations[i] = resolvePath(locations[i]).trim();}}else {this.configLocations = null;}
}

2、调用resolvePath方法解析配置文件路径中的占位符,源码如下:

// 解析给定的路径,必要时用相应的环境属性值替换占位符。应用于配置位置。
protected String resolvePath(String path) {// 获取环境,解决所需的占位符return getEnvironment().resolveRequiredPlaceholders(path);
}

3、调用getEnvironment方法获取环境信息,如果没有指定spring的环境信息,通过createEnvironment获取默认的环境,也就是spring的标准环境。getEnvironment方法源码如下:

// 获取spring的环境信息,如果没有指定,获取到的时默认的环境
@Override
public ConfigurableEnvironment getEnvironment() {if (this.environment == null) {this.environment = createEnvironment();}return this.environment;
}

4、调用createEnvironment方法获取默认的环境(spring的标准环境),使用StandardEnvironment无参构造创建对象。源码如下:

// 获取默认的环境
protected ConfigurableEnvironment createEnvironment() {return new StandardEnvironment();
}

Spring的标准环境StandardEnvironment

Spring的标准环境StandardEnvironment适合在非web应用程序中使用。

在AbstractApplicationContext类的createEnvironment方法中会调用StandardEnvironment的无参构造方法创建环境对象。
1、调用StandardEnvironment的无参构造方法,该方法中没有任何逻辑处理,源码如下:

public StandardEnvironment() {}

2、StandardEnvironment类是AbstractEnvironment抽象类的子类,因此使用StandardEnvironment的无参构造创建对象时会调用父类AbstractEnvironment的无参构造方法。AbstractEnvironment在下文中有描述。

3、重写AbstractEnvironment类中的customizePropertySources方法,用于设置属性源,该方法通过父类进行回调。
该方法会获取JVM系统属性和环境属性并设置到MutablePropertySources类中存放属性源的CopyOnWriteArrayList中。
1)JVM系统属性通过System.getProperties()获取;
2)环境属性通过System.getenv()获取。
StandardEnvironment类中customizePropertySources方法源码如下:

// 设置属性源,JVM系统属性中的属性将优先于环境属性中的属性。
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {/*** 1、MutablePropertySources类中使用CopyOnWriteArrayList存储属性源,集合中存储PropertySource的子类* 2、PropertiesPropertySource是PropertySource的子类,PropertySource类中有三个成员变量* 		1)logger:日志对象* 		2)name:用来保存属性源名称* 		3)source:用来保存属性源中的属性*/// getSystemProperties():通过System.getProperties()获取JVM属性键值对,并转成MappropertySources.addLast(new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));// getSystemEnvironment():通过System.getenv()获取环境属性键值对,并撰成MappropertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

4、StandardEnvironment类中设置了两个静态常量:
1)systemEnvironment:以系统环境为属性源
2)systemProperties:以JVM系统属性为属性源

/** System environment property source name: {@value}.* 系统环境属性源名:{@value}。 */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";/** JVM system properties property source name: {@value}.* JVM系统属性属性源名称:{@value}。*/
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

Spring的抽象环境AbstractEnvironment

StandardEnvironment类是AbstractEnvironment抽象类的子类,因此使用StandardEnvironment的无参构造创建对象时会调用父类AbstractEnvironment的无参构造方法。

1、AbstractEnvironment的无参构造方法,该方法会调用AbstractEnvironment的有参构造方法,源码如下:

public AbstractEnvironment() {this(new MutablePropertySources());
}

2、AbstractEnvironment的有参构造
该方法的主要做三件事:
1)给成员变量赋值
2)创建属性源属性解析器
3)调用子类重写的customizePropertySources方法(方法回调)。虽然方法回调在成员变量的赋值之后,但由于是引用传递,所以通过成员属性可以获取到改变之后的值。

// 使用了模板方法设计模式。
// 给成员变量赋值,并调用子类重写的方法,对propertySources进行操作。
protected AbstractEnvironment(MutablePropertySources propertySources) {// 给全局变量 可变属性源 赋值this.propertySources = propertySources;// 创建属性解析器:PropertySourcesPropertyResolver 属性源属性解析器this.propertyResolver = createPropertyResolver(propertySources);// 自定义属性源,此处回调子类重写的方法。子类通过重写该方法可以操作propertySources。spring标准环境StandardEnvironment重写了该方法customizePropertySources(propertySources);
}

3、调用createPropertyResolver创建属性解析器,用于解析属性值中的占位符并进行替换。

// 在创建环境时,需要创建属性解析器
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {return new PropertySourcesPropertyResolver(propertySources);
}

4、AbstractEnvironment的成员属性

// 指示Spring忽略系统环境变量,默认值为"false"。
// false表示不会忽略系统环境变量,此时getSystemEnvironment方法会调用System.getenv()获取环境属性
// true表示会忽略系统的环境变量,此时getSystemEnvironment方法会返回一个空的Map
public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";// 指定系统启动时使用哪些配置文件,可以使用逗号隔开
public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";// 指定系统启动时使用默认的配置文件,可以使用逗号隔开
public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";// 保留的默认的配置文件的名称,如果没有显式设置默认配置文件名称,也没有显式设置活动配置文件名称,则默认情况下该配置文件将自动激活。
protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";// 日志对象
protected final Log logger = LogFactory.getLog(getClass());//系统启动时使用的配置文件
private final Set<String> activeProfiles = new LinkedHashSet<>();// 默认配置文件
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());// 可变属性源,使用该成员变量保存属性源及通过该属性源获取的属性
private final MutablePropertySources propertySources;// 可配置的属性解析器
private final ConfigurablePropertyResolver propertyResolver;

http://www.mrgr.cn/p/83663821

相关文章

通过RPM方式安装,升级,卸载,以及配置使用MySQL

通过RPM方式安装&#xff0c;升级&#xff0c;卸载&#xff0c;以及配置使用MySQL 一、下载 MySQL是一种开源的关系数据库管理系统&#xff0c;被广泛应用于各种业务应用中。本文将讲解如何下载和安装MySQL的rpm安装包。 下载rmp安装包有多种方式&#xff1a; 1、官网下载 …

视频内存过大如何压缩变小?这个压缩方法了解一下

在日常生活中&#xff0c;不管是日常随手拍的视频还是在工作中遇到的视频文件&#xff0c;在编辑处理的时候&#xff0c;如果视频的内存过大&#xff0c;不仅会占用很大的内存&#xff0c;在传送的时候也会花费很长时间&#xff0c;这时候将视频给压缩一下就可以很好的解决这一…

STM32入门学习之外部中断

1.STM32的IO口可以作为外部中断输入口。本文通过按键按下作为外部中断的输入&#xff0c;点亮LED灯。在STM32的19个外部中断中&#xff0c;0-15为外部IO口的中断输入口。STM32的引脚分别对应着0-15的外部中断线。比如&#xff0c;外部中断线0对应着GPIOA.0-GPIOG.0&#xff0c;…

论文笔记:Fine-Grained Urban Flow Prediction

2021 WWW 1 intro 细粒度城市流量预测 两个挑战 细粒度数据中观察到的网格间的转移动态使得预测变得更加复杂 需要在全局范围内捕获网格单元之间的空间依赖性单独学习外部因素&#xff08;例如天气、POI、路段信息等&#xff09;对大量网格单元的影响非常具有挑战性——>论…

【客户案例】云联壹云助力某保险公司搭建公有云费用管理平台

客户介绍 客户成立于 1996 年 11 月&#xff0c;现已拥有逾 2000 名员工和 12000 名营销员&#xff0c;为 280 万客户提供专业的金融保险服务。在上海、北京、广东、浙江、江苏、四川、山东、福建、重庆、辽宁、天津、湖北、河北、湖南和陕西等地的 50 多个城市稳步发展&#…

数据结构之顺序表

一、概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存 储。在数组上完成数据的增删查改。 顺序表一般可以分为&#xff1a; 1. 静态顺序表&#xff1a;使用定长数组存储元素。 2. 动态顺序表&#xff1a;使用动…

骨传导耳机它的工作原理是什么?骨传导耳机长期使用会有脑损伤吗?

骨传导耳机&#xff0c;就是利用头骨和额骨传导声音头骨和额骨传导声音的耳机&#xff0c;这并不是夸大其词&#xff0c;不用惊讶。 骨传导耳机的工作原理其实也很简单&#xff0c;声波通过颅骨、颌骨等头部骨头的振动&#xff0c;直接将声音传到内耳&#xff0c;直接避免接触到…

DataEase开源BI工具安装_数据全量_增量同步_大屏拖拽自动生成_多数据源支持_数据血缘分析---大数据工作笔记0183

我这里用的是Centos7.9安装的 可以通过uname -p来查看一下我们的电脑架构,可以看到是x86_64架构的 我们下第一个,这个是x86架构的,第二个arm架构的 然后解压到/opt/module中 然后再去重命名一下文件夹. 推荐200G 本地模式的功能比较多 推荐100G

立即报名 | AI +Serverless Meetup 上海站 8 月 5 日等你相约!

自 2021 年 5 月后&#xff0c;KubeSphere 社区与上海的各位小伙伴已阔别两年&#xff0c;许久不见&#xff0c;甚是想念&#xff01;2023 年 8 月 5 日&#xff0c;KubeSphere 社区将走进上海组织一场主题为 “AI Serverless” 的 Meetup。此外&#xff0c;云原生也依旧是本次…

windows中注册redis服务启动时报1067错误

注册完redis服务&#xff0c;打开计算机 服务时确实有redis服务存在&#xff0c;但是点击启动时却报1067错误&#xff0c;而命令行用redis-server.exe redis.windows.conf 命令却也可以启动 查看6379的端口也没有被占用&#xff08;netstat -ano | findstr :6379&#xff09; …

【二开】JeecgBoot-vue3二次开发 前端 扩展online表单js增强等-初始化列表之后执行

【二开】JeecgBoot-vue3二次开发 前端 扩展online表单js增强等-初始化列表之后执行 二开位置 OnlineAutoList.js.initAutoList 定义方法 /*** 初始化列表之后执行* js增强* param tableColumns* returns {Promise<void>|*}*/onlineTableContext["afterInitAutoList…

4-Linux组管理和权限管理

Linux组管理和权限管理 Linux组的基本介绍文件/目录的所有者组的创建文件/目录所在的组其它组改变用户所在的组权限的基本介绍第0-9位说明rwx权限详解rwx 修饰文件时rwx修饰目录时 修改权限第一种方式&#xff1a;、-、 变更权限第二种方式&#xff1a;通过数字变更权限 修改文…

文档管理NAS储存安全吗?

关键词&#xff1a;私有化、知识管理系统、文档管理、群晖NAS、协同编辑 随着企业不断发展扩大&#xff0c;企业的知识文档也逐渐增多&#xff0c;很多企业方便管理及考虑数据安全问题会将文件数据储存至NAS。 但将企业文档数据放在NAS上就足够安全的吗&#xff1f; 天翎文档管…

Mybatis源码解析(三)------SqlSession

Mybatis源码解析&#xff08;三&#xff09;------SqlSession 序言SqlSession接口SqlSession的实现类DefaultSqlSessionSelect获取Statement查询 序言 Mybatis里面的核心就是SqlSession这个接口&#xff0c;前面我们已经研究了Mybatis的配置过程和Mapper的注册过程&#xff0c…

【数学建模】时间序列分析

文章目录 1. 条件2. 模型分类3. SPSS处理时间序列 1. 条件 1.使用于具有时间、数值两种要素 2.数据具有周期性可以使用时间序列分解 2. 模型分类 叠加模型【YTSCI】 序列的季节波动变化越来越大&#xff0c;反映变动之间的关系发生变化乘积序列【YTSC*I】 时间序列波动保持恒…

舌体分割的初步展示应用——依托Streamlit搭建demo

1 前言 去年在社区发布了有关中医舌象诊断的博文&#xff0c;其中舌象识别板块受到了极高的关注和关注。&#x1f60a;最近&#xff0c;我接触到了Python的Streamlit库&#xff0c;它可以帮助数据相关从业人员轻松搭建数据看板。本文将介绍如何使用Streamlit构建舌体分割的演示…

网络层IP协议的基本原理 数据链路层ARP协议 域名解析以及一些重要技术

目录 1 网络层IP协议协议头格式网段划分DHCPCIDR&#xff1a;基于子网掩码的划分方式特殊的IP号IP地址的数量限制私有IP地址和公网IP地址路由路由表 2 数据链路层 — 局域网的转发问题以太网认识以太网以太网帧格式局域网通信原理 MTUMTU对IP协议的影响MTU对UDP协议的影响MTU对…

脑电信号处理与特征提取——6.运用机器学习技术和脑电进行大脑解码(涂毅恒)

目录 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分析 6.4 代码解读 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分…

谷粒商城第七天-商品服务之分类管理下的分类的拖拽功能的实现

目录 一、总述 1.1 前端思路 1.2 后端思路 二、前端实现 2.1 判断是否能进行拖拽 2.2 收集受影响的节点&#xff0c;提交给服务器 三、后端实现 四、总结 一、总述 这个拖拽功能对于这种树形的列表&#xff0c;整体的搬迁是很方便的。但是其实现却并不是那么的简单。 …

如何在不使用脚本和插件的情况下手动删除 3Ds Max 中的病毒?

如何加快3D项目的渲染速度&#xff1f; 3D项目渲染慢、渲染卡顿、渲染崩溃&#xff0c;本地硬件配置不够&#xff0c;想要加速渲染&#xff0c;在不增加额外的硬件成本投入的情况下&#xff0c;最好的解决方式是使用渲云云渲染&#xff0c;在云端批量渲染&#xff0c;批量出结…