重看Spring聚焦Environment分析

目录

一、理解Environment的设计

(一)整体理解

(二)聚焦Profiles分析

(三)聚焦Properties分析

二、Environment类图结构分析

三、PropertyResolver源码分析

(一)源码展示说明

(二)源码理解分析

四、Environment源码分析

五、ConfigurableEnvironment源码分析

(一)源码展示

(二)如何理解

六、AbstractEnvironment简单说明

七、其与IOC容器的关系分析

(一)单独来看

(二)关系型分析来看


一、理解Environment的设计

(一)整体理解

之前我们在分析分析SpringBoot启动配置原理_springboot启动机制-CSDN博客的时候对应Environment已经有一定的了解了,本次对其聚焦进行更加深层次的理解和分析:

Environment模块在 Spring 中主要负责管理应用程序的配置和环境(定义为一组 profile配置文件)相关的信息,每个 profile 对应一个特定的应用程序部署环境,比如开发、测试、生产等。

在这些 profile 中,可以包含各种属性,比如数据库连接信息、服务器端口、日志级别等。而

对应的属性在 Spring 中被表示为键值对,其中键是属性的名称,值是属性的取值。属性可以通过不同的方式进行配置,比如在属性文件中、通过系统属性、操作系统环境变量等。

(二)聚焦Profiles分析

专注于 Environment 模块中Profiles 的核心概念,从设计上来看其基本功能的话,个人觉得主要是以下三方面:

  1. 环境分离与配置隔离: Profiles 允许将不同的配置信息与不同的部署环境(如开发、测试、生产)进行关联。通过定义不同的 profile,可以在不同的环境中使用不同的配置信息,从而实现了环境之间的隔离和配置的分离。这样做有助于提高应用程序的灵活性和可维护性。

  2. 适应多种环境: Spring Environment 允许为每个 profile 定义不同的配置信息,这使得应用程序可以适应多种不同的部署环境。比如在开发环境中可以使用内存数据库,而在生产环境中则使用真实的数据库。

  3. 条件化配置: Profiles 支持条件化配置,可以根据运行时的条件选择加载特定的 profile。这可以通过 @Profile 注解或在配置文件中使用 spring.profiles.active 属性来实现。这样可以根据运行时的条件动态地决定使用哪个 profile,进而决定加载哪些配置信息。

这里如果看源码的话,Profiles 是支持继承的,即可以定义一个通用的 profile,并在其他 profile 中引用或继承这个通用的 profile来避免重复定义相似的配置信息。同时Profiles 可以与外部化配置(如属性文件、YAML 文件)结合使用,通过不同的 profile 加载不同的外部化配置文件。

(三)聚焦Properties分析

Properties负责管理应用程序的配置信息主要功能如下:

  1. 抽象化和统一访问: Properties 提供了一个抽象化的方式来管理配置信息,通过统一的接口访问配置信息,使得应用程序不需要关心配置信息的具体来源,可以将其抽象为一组键值对。

  2. 支持多种配置源: Properties 支持从多种不同的配置源中获取配置信息。这些配置源可以包括属性文件(如 .properties 文件、.yaml 文件)、系统属性、操作系统环境变量等。

  3. 属性解析和占位符替换: Properties 支持属性解析和占位符替换,可以在配置文件中使用 ${...} 占位符来引用其他配置属性,以及在运行时动态替换这些占位符为实际的属性值。

  4. 属性优先级: Properties 支持属性优先级设置,可以指定不同来源的属性之间的优先级。例如,系统属性可以优先于配置文件属性,配置文件属性可以优先于默认值。

  5. 监听器支持: Properties 支持监听器(EnvironmentPostProcessor),可以在 Spring 应用程序启动时对 Properties 进行修改和定制化。

二、Environment类图结构分析

Environment 接口本身是一个顶层接口,Environment 接口的实现类通常是通过组合其他类来实现其功能的,基本关系图梳理如下:(其实这部分读源码理解对平时的开发有很大的指导性,建议直接阅读下并应用到平时的开发中)

整体来看的话,PropertyResolverConfigurablePropertyResolver 提供了属性解析和配置属性的功能,EnvironmentConfigurableEnvironment 则扩展了属性解析器和配置管理器的功能,从而实现了更全面的环境配置。

AbstractEnvironmentStandardEnvironmentEnvironment 接口的具体实现类,提供了默认的环境配置功能。ConfigurableWebEnvironmentStandardReactiveWebEnvironmentStandardServletEnvironment 则是针对特定类型的 Web 应用程序环境配置的具体实现类。

类/接口描述
PropertyResolver定义了解析属性的方法,提供获取属性值、解析占位符等功能。
ConfigurablePropertyResolverPropertyResolver 扩展,提供配置属性的功能,如设置属性、忽略属性等。
Environment整个Spring应用环境,提供获取配置属性、管理 Profiles、处理属性源等功能。
ConfigurableEnvironmentEnvironment 扩展,定义了配置环境的一些额外功能,如设置激活的 Profiles、添加属性源等。
AbstractEnvironmentEnvironment 的抽象实现类,同时也实现了 ConfigurableEnvironment 接口,提供了通用的环境配置功能和默认实现。
StandardEnvironmentAbstractEnvironment 的具体实现类,提供了对系统属性、环境变量、JNDI、PropertySource 等的支持,是 Spring 中最常用的环境实现之一。
ConfigurableWebEnvironmentConfigurableEnvironment 扩展,特定于 Web 应用程序的环境配置,提供了一些额外的 Web 相关的配置功能,如 Servlet 上下文、Servlet 配置等。
StandardReactiveWebEnvironmentConfigurableWebEnvironment 的具体实现类,适用于响应式 Web 应用程序的环境配置,提供了对响应式 Web 环境的支持。
StandardServletEnvironmentConfigurableWebEnvironment 的另一个具体实现类,适用于传统的 Servlet Web 应用程序的环境配置,提供了对 Servlet 上下文和 Servlet 配置的支持。

我们下面会通过几个重点的接口类进行分析。

三、PropertyResolver源码分析

(一)源码展示说明

PropertyResolver 接口是用于解析属性的基础接口,定义了获取属性值、解析占位符等方法。

public interface PropertyResolver {/*** 根据给定的属性键获取属性值。* @param key 属性键* @return 对应的属性值,如果属性不存在则返回 null*/String getProperty(String key);/*** 根据给定的属性键获取属性值,如果属性不存在则返回默认值。* @param key 属性键* @param defaultValue 默认值* @return 对应的属性值,如果属性不存在则返回默认值*/String getProperty(String key, String defaultValue);/*** 检查是否存在给定属性键的属性。* @param key 属性键* @return 如果存在则返回 true,否则返回 false*/boolean containsProperty(String key);/*** 解析给定文本中的占位符,并替换为实际的属性值。* @param text 要解析的文本* @return 解析后的文本*/String resolvePlaceholders(String text);
}

(二)源码理解分析

PropertyResolver 接口就像是一个通用的属性查询器,它专门负责查找应用程序中的配置信息,比如数据库连接、服务端口等。它的设计思想是让应用程序的各个组件不必自己去查找这些配置信息,而是交给一个专门的工具来处理。这样做有两个好处,一是提高了代码的模块化和可维护性,二是让配置信息更容易被统一管理和修改,让程序更加灵活和易用。

四、Environment源码分析

Environment 表示整个应用程序环境的接口,定义了一些方法来获取配置属性、处理 Profiles、管理属性源等。部分源码展示如下:

import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.Profiles;public interface Environment extends PropertyResolver {/*** 获取活动的 Profiles。* @return 活动的 Profiles*/String[] getActiveProfiles();/*** 获取默认的 Profiles。* @return 默认的 Profiles*/String[] getDefaultProfiles();/*** 检查是否接受给定的 Profiles。* @param profiles 要检查的 Profiles* @return 如果接受则返回 true,否则返回 false*/boolean acceptsProfiles(Profiles profiles);// 其他方法...
}

Environment 接口继承自 PropertyResolver 接口,因此它具有属性解析的能力,可以通过 getProperty 方法来获取配置属性的值,通过 resolvePlaceholders 方法来解析属性值中的占位符。除此之外,Environment 还定义了一些关于 Profiles 管理的方法,用于管理应用程序的配置文件、属性源等。在实际应用中,Spring Framework 提供了多个具体实现类,如 StandardEnvironmentStandardServletEnvironment 等,用于实现 Environment 接口的功能,并为应用程序提供环境配置的支持。

五、ConfigurableEnvironment源码分析

(一)源码展示

继承自 Environment 接口,并定义了一些额外的配置管理功能。展示了部分方法和属性:

import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;public interface ConfigurableEnvironment extends Environment {/*** 设置活动的 Profiles。* @param profiles 活动的 Profiles*/void setActiveProfiles(String... profiles);/*** 添加一个属性源。* @param propertySource 要添加的属性源*/void addPropertySource(PropertySource<?> propertySource);/*** 获取所有的属性源。* @return 所有的属性源*/MutablePropertySources getPropertySources();// 其他方法...
}

(二)如何理解

ConfigurableEnvironment 接口的设计就像是给应用程序一个"可塑造的环境",让你可以根据需要来定制和管理你的应用程序的环境。

想象一下,应用程序就像是一个小花园,而 ConfigurableEnvironment 就是提供了一些工具,让你可以在这个花园中种植不同的花草、设计不同的景观。

  • setActiveProfiles 方法就像是给你一桶颜料,让你可以选择不同的颜色来装饰你的花园。你可以选择激活不同的 "profile",比如 "开发"、"测试"、"生产" 等,以适应不同的环境和需求。
  • addPropertySource 方法就像是给你提供了一些花盆,让你可以往花园里添加不同种类的植物。你可以通过添加属性源来灵活地管理你的配置信息,比如从文件中读取配置、从数据库中读取配置等。
  • getPropertySources 方法就像是给你提供了一个花园地图,让你可以清楚地了解你花园中都有哪些植物。你可以通过获取属性源来查看和管理你的配置信息。

ConfigurableEnvironment 就是为了让应用程序更加灵活和可塑造而设计的可以适应不同的场景和需求。

六、AbstractEnvironment简单说明

AbstractEnvironment 使用模板方法模式定义了一个基本骨架,getPropertySources() 方法就是一个典型的模板方法,而具体的属性源管理实现则留给了子类去完成。

具体来说,在 AbstractEnvironment 的构造函数中,会初始化 propertySources 对象,然后通过 getPropertySources() 方法,子类可以获取这个 propertySources 对象,并对其进行操作,完成具体的属性源管理逻辑。

有几个主要的子类都有特定的用途和环境条件:

  1. StandardEnvironment:AbstractEnvironment 的标准实现,用于标准的应用程序环境。适用于大多数的应用场景,提供了对系统属性、环境变量等的支持,可以用于加载和管理应用程序的配置信息。

  2. StandardServletEnvironment:扩展了 StandardEnvironment,并添加了对 Servlet 上下文参数、Servlet 初始化参数等的支持。适用于基于 Servlet 容器(如 Tomcat、Jetty 等)的应用程序环境。

  3. StandardReactiveWebEnvironment:是针对响应式 Web 环境的实现,适用于使用 Spring WebFlux 框架的应用程序。扩展了 StandardEnvironment,并添加了对响应式 Web 环境的特定支持。

  4. MockEnvironment:用于测试目的的环境模拟类,提供模拟的环境实现,用于在单元测试和集成测试中模拟不同的环境条件,如不同的配置信息、Profiles 等。

七、其与IOC容器的关系分析

(一)单独来看

  1. IOC 容器的作用:负责管理应用程序中的对象(Bean),并处理它们之间的依赖关系。IOC 容器通过将对象的创建、组装和管理工作交给容器来实现对象之间的解耦和松耦合。

  2. Environment 的作用:用于表示应用程序环境的接口,负责管理和处理应用程序的配置信息,比如配置文件、系统属性等,提供一种统一的方式来获取和解析配置属性,使得应用程序可以根据不同的环境条件来加载不同的配置信息。

(二)关系型分析来看

IOC 容器需要获取应用程序的配置信息来创建和初始化对象,而 Environment 就是负责管理和提供这些配置信息的。在 Spring 应用程序启动时,IOC 容器会通过 Environment 接口来获取配置信息,并根据配置信息来完成 Bean 的装配和初始化工作。

通常情况下,IOC 容器会将 Environment 对象作为一个重要的组件来进行配置和初始化,以确保应用程序能够正确地获取和使用配置信息。在 Spring Framework 中,ApplicationContext 接口是 IOC 容器的主要实现类之一,通常会与 Environment 接口紧密配合,以实现对配置信息的管理和使用。具体可见:分析SpringBoot启动配置原理_springboot启动机制-CSDN博客文章浏览阅读1.5w次,点赞10次,收藏28次。分析SpringBoot启动配置原理:给出整体初步分析和对应流程图,并从三方面进行展开分析(SpringApplication构造过程分析+SpringApplication启动过程分析+SpringBoot自动配置分析)_springboot启动机制https://blog.csdn.net/xiaofeng10330111/article/details/130903779?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171389467716800182742131%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171389467716800182742131&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-130903779-null-null.nonecase&utm_term=%E5%90%AF%E5%8A%A8&spm=1018.2226.3001.4450源码或官方文章

Java-based Container Configuration :: Spring Framework

Bean Scopes :: Spring Framework

Container Overview :: Spring Framework

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

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

相关文章

C语言学习/复习36

一、程序的环境与预处理 二、翻译环境与执行环境 三、运行环境 四、预编译(预处理)详解

mac电脑搭建vue环境(上篇)

第一步&#xff1a;mac电脑要有homebrew&#xff0c;如何安装homebrew 点击下方 MAC安装homebrew-CSDN博客 第二步&#xff1a;homebrew安装node.js 第三步&#xff1a;安装npm 第四步&#xff1a;安装webpack 第五步&#xff1a;安装vue脚手架 第六步&#xff1a;可以在…

NumPy 1.26 中文官方指南(一)

NumPy 用户指南 原文&#xff1a;numpy.org/doc/1.26/user/index.html 本指南是一个概述&#xff0c;解释了重要特性&#xff1b;细节请参阅 NumPy 参考文档。 入门指南 什么是 NumPy? 安装 NumPy 快速入门 NumPy&#xff1a;初学者的绝对基础 基础知识和用法 NumPy 基础…

工信部绿色工厂、绿色设计产品、绿色供应链企业、绿色园区名单数据集(2017-2022年)

01、数据简介 工信部致力于推动制造业的绿色转型&#xff0c;为了表彰在绿色制造领域取得显著成绩的企业和园区&#xff0c;工信部发布了绿色工厂公示名单、绿色设计产品公示名单、绿色供应链企业公示名单和绿色园区公示名单。 这些企业和园区在绿色制造方面做出了卓越的贡献…

MySQL__锁

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a; MySQL__锁&#xff09; ⏱️ 创作时间&#xff1a;2024年04月27日 ———————————————— 这里写目录…

刷题训练之前缀和

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握前缀和算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷题…

【Hadoop】-HDFS的存储原理[4]

目录 前言 一、fsck命令 1、HDFS副本块数量的配置 2、fsck命令查看文件的副本数 3、block配置 二、NameNode元数据 1、edits文件 2、fsigame文件 3、NameNode元数据管理维护 4、元数据合并控制参数 5、SecondaryNameNode的作用 三、HDFS数据的读写流程 1、数据写入…

Pytorch 之torch.nn初探 卷积--Convolution Layers

任务描述 本关任务&#xff1a; 本关提供了一个Variable 类型的变量input&#xff0c;按照要求创建一 Conv1d变量conv&#xff0c;对input应用卷积操作并赋值给变量 output&#xff0c;并输出output 的大小。 相关知识 卷积的本质就是用卷积核的参数来提取原始数据的特征&a…

前端HTML5学习1(新增布局,状态,列表,文本,表单控件标签)

前端HTML5学习1&#xff08;新增布局&#xff0c;状态&#xff0c;列表&#xff0c;文本&#xff0c;表单控件标签&#xff09; 新增布局标签新增状态标签新增列表标签新增文本标签新增表单控件属性input新增属性值 新增布局标签 HTML5 引入了许多新的语义化标签&#xff0c;用…

【MySQL】A01、性能优化-参数监控分析

1、参数监控 1.1、MySQL command 查看 mysql>SHOW STATUS; &#xff08;服务器状态变量&#xff0c;运行服务器的统计和状态指标&#xff09; mysql> SHOW VARIABLES;&#xff08;服务器系统变量&#xff0c;实际上使用的变量的值&#xff09; mysql> SHOW STATUS …

SpringBoot---------Hutool

第一步&#xff1a;引入依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-parent</artifactId><version>5.7.17</version></dependency> 第二步&#xff1a;各种用法 ①生成随机数 //生成验证码 String s …

Linux磁盘管理与文件系统

目录 一.磁盘基础 磁盘结构 二.MBR 磁盘分区结构 三.文件系统类型 XFS文件系统 SWAP&#xff0c;交换文件系统 四.磁盘分区 linux系统添加并使用新硬盘的步骤 五 .创建文件系统 mkfs mkfs命令 挂载、卸载文件系统 挂载文件系统、ISO镜像到指定文件夹 ​编辑umount…

Redis可视化工具RedisInsight

下载地址&#xff1a;RedisInsight - The Best Redis GUIRedisInsight provides an intuitive and efficient graphical interface for Redis, allowing you to interact with your databases and manage your data.https://redis.com/redis-enterprise/redis-insight/#insight…

IDEA上配置Maven环境

1.选择IDEA中的Setting 2.搜索maven 3.设置IDEA使用本地安装的Maven&#xff0c;并修改配置文件路径 配置文件&#xff0c;本地仓库&#xff0c;阿里云仓库配置及路径教程 在IDEA上配置完成。

【Linux内核驱动基础】从零开始手搓一个从上层应用到底层驱动的IO口代码

【Linux内核驱动基础】从零开始手搓一个从上层应用到底层驱动的IO口控制代码 文章目录 【Linux内核驱动基础】从零开始手搓一个从上层应用到底层驱动的IO口控制代码一、驱动基础认知1.为什么要学会写驱动2.文件名与设备号3.open函数从上层打通到底层硬件的详细过程 二、基于内核…

【强训笔记】day4

NO.1 思路&#xff1a;利用滚动数组&#xff0c;迭代一个Fibonacci数列&#xff0c;给出三个值进行循环迭代&#xff0c;当n<c时&#xff0c;说明n在b和c之间&#xff0c;这里只需要返回c-n和n-b的最小值就可以了。 代码实现&#xff1a; #include<iostream>using n…

打印给定数组中每一个数字

如何给定1-10的数字 #include<stdio.h> int main() {int arr[] { 1,2,3,4,5,6,7,8,9,10 };// 0 9//[]--下标引用操作符int i;int sz sizeof(arr) / sizeof(arr[0]);//10个数for (i 0; i < sz; i){printf("%d ", arr[i]);}re…

centos7使用源码安装方式redis

安装编译源码的工具gcc yum install -y gcc下载源码 源码下载地址 https://download.redis.io/releases/ 注意事项 不建议安装最新版本redis&#xff0c;所以我这里选择6.2.6版本 下载 wget https://download.redis.io/releases/redis-6.2.6.tar.gz解压 tar -zxvf redis-…

单片机通讯协议

参考&#xff1a;江科大单片机教程 STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili IIC通讯协议SPI通信协议UARTCANUSB速度100k-400khz4Mhz-线数2 CLK,DATA4CLK,ENB,IO,OI额外设备一主多从一主多从 一般不用自己写&#xff0c;都有相应的库或官方提供相应的&#…