重看Spring聚焦Environment分析

news2024/10/5 20:23:59

目录

一、理解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.coloradmin.cn/o/1619376.html

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

相关文章

广东理工学院携手泰迪智能科技成功部署人工智能实验室

广东理工学院是经国家教育部批准设立的全日制普通本科院校&#xff0c;入选全国应用型人才培养工程培养基地、国家级众创空间试点单位、广东省高校电子商务人才孵化基地。开设34个本科专业&#xff0c;涵盖工学、经济学、管理学、文学、艺术学、教育学等6大学科门类&#xff0c…

Power BI 如何创建页面导航器?(添加目录按钮/切换页面按钮)

Power BI 中页导航是什么&#xff1f; 在Power BI中&#xff0c;页导航&#xff08;Page Navigation&#xff09;是指在报告中创建多个页面&#xff08;页&#xff09;&#xff0c;然后允许用户在这些页面之间进行导航的功能。 如下图所示&#xff0c;页导航的选项和报告中的…

李飞飞团队《2024 年人工智能指数报告》AI十大趋势:中国AI专利数全球第一

《2024 年人工智能指数报告》 当地时间4月15日&#xff0c;斯坦福大学“以人为本”人工智能研究院&#xff08;Human Centered Artificial Intelligence&#xff0c;简称HAI&#xff09;发布了第七个年度AI Index报告&#xff0c;这是关于AI行业现状的最全面的报告之一。 报告…

聊聊go语言中的GMP模型

写在文章开头 我们都知道go语言通过轻量级线程协程解决并发问题&#xff0c;按照go语言的思想这些协程运行完成后即焚&#xff0c;那么go语言如何保证并发线程有序获取协程呢&#xff1f; 带着这个问题我们从go语言底层的源码来阐述这个问题&#xff1a; Hi&#xff0c;我是 s…

K-means聚类算法:如何在杂乱无章的数据中找出规律?

什么是K-means聚类算法&#xff1f; 在编程的世界里&#xff0c;K-means聚类算法就像一位无私的指路人&#xff0c;它不需要我们给出明确的指示&#xff0c;只需要我们提供数据&#xff0c;它就能帮助我们找到数据的归属&#xff0c;找到数据的“家”。 K-means聚类算法的名字…

经典的目标检测算法有哪些?

一、经典的目标检测算法有哪些&#xff1f; 目标检测算法根据其处理流程可以分为两大类&#xff1a;One-Stage&#xff08;单阶段&#xff09;算法和Two-Stage&#xff08;两阶段&#xff09;算法。以下是一些经典的目标检测算法&#xff1a; 单阶段算法: YOLO (You Only Loo…

【御控工业物联网】JAVA JSON结构转换、JSON结构重构、JSON结构互换(5):对象To对象——转换映射方式

御控官网&#xff1a;https://www.yu-con.com/ 文章目录 御控官网&#xff1a;[https://www.yu-con.com/](https://www.yu-con.com/)一、JSON结构转换是什么&#xff1f;二、术语解释三、案例之《JSON对象 To JSON对象》四、代码实现五、在线转换工具六、技术资料 一、JSON结构…

Linux中的vi与vim:编辑器的王者之争与深度探索

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Linux的起源与发展 2、vi与vim的历史与发展 …

【C++】手撕list(list的模拟实现)

目录 01.节点 02.迭代器 迭代器运算符重载 03.list类 &#xff08;1&#xff09;构造与析构 &#xff08;2&#xff09;迭代器相关 &#xff08;3&#xff09;容量相关 &#xff08;4&#xff09;访问操作 &#xff08;5&#xff09;插入删除 我们在学习数据结构的时候…

Laravel 6 - 第十一章 中间件

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

Unity 如何制作和发布你的 Package

一、制作你的第一个 Package Unity Package 不做过多赘述&#xff0c;像 URP 本质上也是一个 Package&#xff0c;在 Unity 中可以通过菜单栏 → Window → Package manager 来管理你当前的所有 Package 本篇文章主要介绍&#xff1a;如何制作并发布属于你的 Package 1.1 Pac…

将本地项目推送至gitlab仓库

1. gitlab上新建一个空白项目 gitlab上点击new project按钮&#xff0c;新建一个项目 新建空白项目 项目名称与本地新建项目名称相同&#xff0c;其余根据具体需要选择 2. 初始化本地仓库并commit项目 进入本地项目根目录下&#xff0c;右击 git bash here打开命令窗口 初始化…

8.4.2 实验2:配置Trunk

1、实验目的 通过本实验可以掌握&#xff1a; Native VLAN 的含义和配置。IEEE802.1q 封装Trunk 配置和调试方法。 2、实验拓扑 配置 Trunk 的实验拓扑如下图所示。 图8-6 配置 Trunk 的实验拓扑 3、实验步骤 3.1 在交换机S1、S2上创建 VLAN 并把端口划分到相应的VLAN中 …

ASP.NET教务管理平台-权限及公共模块设计与开发

摘 要 随着教育改革的不断深化&#xff0c;高等院校的建设与发展对国民整体素质的提高起着越来越重要的作用&#xff0c;建立一套能够适应这些改变的行政管理方案也就显得尤为重要。对于教务处来说&#xff0c;将信息技术用于校务管理中便是迫切的要求。 教务系统中的用户…

ROS 2边学边练(33)-- 写一个静态广播(C++)

前言 通过这一篇我们将了解并学习到如何广播静态坐标变换到tf2&#xff08;由tf2来转换这些坐标系&#xff09;。 发布静态变换对于定义机器人底座与其传感器或非移动部件之间的关系非常有用。例如&#xff0c;在以激光扫描仪中心的坐标系中推理激光扫描测量数据是最简单的。 这…

Ventus(承影):基于RISC V的开源GPGPU

Ventus&#xff08;承影&#xff09;&#xff1a;基于RVV的开源GPGPU 清华大学集成电路学院dsp-lab的承影RVV GPGPU设计文档。 整体目标 提供一个开源的基于RVV的GPGPU实现方案&#xff0c;并给出软件映射方案、指令集&#xff08;支持的指令及特性、添加的自定义指令&#xf…

15.接口自动化学习-Mock(挡板/测试桩)

场景&#xff1a; 新需求还未开发时&#xff0c;使用mock提早介入测试&#xff0c;等后边开发后&#xff0c;进行调试 三方接口返回效率低&#xff0c;使用mock技术走通流程 1.mock方式 &#xff08;1&#xff09;如果会写django或flask,可以写简单对应的代码 &#xff08;…

小米一面:说说MVC与设计模式的关系

前言 大家好&#xff0c;我叫阿杆&#xff0c;不叫阿轩。 先来看看面试环节吧。 面试官&#xff1a;请说说MVC模式是基于哪种设计模式的&#xff1f; 求职者&#xff1a;MVC本身不就是一种设计模式吗&#xff1f; 面试官&#xff1a;我的意思是&#xff0c;MVC是基于23中设计…

【04-提升模型性能:集成学习与超参数优化】

文章目录 前言集成学习BaggingBoosting超参数优化随机搜索贝叶斯优化总结前言 在前几篇博文中,我们已经介绍了一些机器学习的基础知识、Scikit-learn的核心工具与技巧,以及如何评估模型性能。本篇博文将重点讲解两个可以显著提升机器学习模型性能的高级策略:集成学习和超参数…

python企业员工培训考试系统django+vue

这次开发的供电公司安全生产考试系统管理员&#xff0c;教师&#xff0c;学生。管理员功能有个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;主观题信息管理&#xff0c;主观题回答管理&#xff0c;主观题评分管理&#xff0c;成绩信息管理&#xff0c;试卷管理…