Spring揭秘:Environment接口应用场景及实现原理!

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Environment接口提供了强大且灵活的环境属性管理能力,通过它,开发者能轻松地访问和配置应用程序运行时的各种属性,如系统属性、环境变量等。同时,Environment接口还支持属性源的定制和扩展,使得开发者能根据实际需求灵活地定制属性的加载和解析方式。

Spring揭秘:Environment接口应用场景及实现原理! - 程序员古德

内容概要

Environment接口提供了强大且灵活的环境属性管理能力,通过它,开发者能轻松地访问和配置应用程序运行时的各种属性,如系统属性、环境变量等。

同时,Environment接口还支持属性源的定制和扩展,使得开发者能根据实际需求灵活地定制属性的加载和解析方式。

核心概念

它能解决了什么问题?

Environment接口在Spring框架主要负责管理和提供应用程序运行时的环境信息,这些信息包括但不限于系统属性、环境变量、命令行参数、配置文件属性等。

以下是Environment接口主要用来解决的一些技术问题:

  1. 属性管理Environment提供了访问应用程序属性的集中机制,可以使用它来读取、设置和管理这些属性,这些属性可以来自不同的源,如系统属性、环境变量、配置文件(如properties或yml文件)等。
  2. 配置灵活性:通过使用Environment,开发者可以在运行时动态地改变或覆盖配置,这增加了配置的灵活性和可定制性,对于需要根据不同环境(如开发、测试、生产等)进行不同配置的应用程序来说尤为重要。
  3. 简化配置访问:在Spring应用程序中,可能需要访问各种配置值,Environment简化了这一过程,通过提供统一且易于使用的API,可以轻松地从代码中访问这些配置值。
  4. 配置源整合:Spring的Environment能够将来自不同源的配置信息整合到一起,提供了一个统一的视图来访问这些配置,这意味着,无论配置信息是存储在系统属性、环境变量还是配置文件中,都可以使用相同的方式来访问它们。
  5. 属性占位符解析Environment还支持属性占位符的解析,这允许在配置中使用占位符来引用其他属性的值,这对于创建基于其他属性值的配置特别有用。
  6. 支持Spring表达式语言:在一些高级用例中,可能需要使用Spring表达式语言(SpEL)来访问或操作配置数据。Environment与SpEL的集成使得这种操作变得更加简单和直接。

它有哪些子类拓展

image-20240311193232629

如上图所示,Environment接口有多个实现类,这些实现类根据用途和配置源的不同而有所区分,以下是Environment接口的一些主要实现类:

  1. StandardEnvironment
    这是Environment接口的最基本实现,用于非Web应用程序,它主要管理JVM级别的系统属性和环境变量,通常,在创建独立的Java应用程序或命令行工具时会使用StandardEnvironment
  2. StandardServletEnvironment
    这是用于基于Servlet的Web应用程序的Environment实现,除了系统属性和环境变量外,它还考虑了Servlet规范定义的配置参数,如Servlet上下文初始化参数和JNDI属性,在Spring MVC应用程序中,通常会使用StandardServletEnvironment
  3. ConfigurableEnvironment
    这是一个可以配置和修改的Environment实现,它通常用作其他更具体环境实现的基类,如StandardEnvironmentAbstractEnvironment。它允许添加、删除或修改属性源(PropertySource)。
  4. ConfigurableWebEnvironment:提供了一个专门用于Web应用程序的环境接口,它扩展了ConfigurableEnvironment接口,这个接口的主要作用是为Web应用程序提供配置环境的能力,同时添加了一些与Web环境相关的特性。

个人思考

ConfigurableEnvironmentConfigurableWebEnvironment有什么区别?

他们都是Spring框架中用于配置和管理应用程序运行环境的接口,然而,它们之间存在一些关键的区别,主要在于它们的应用场景和提供的功能:

1、应用场景

  • ConfigurableEnvironment:这是Spring框架中用于配置和管理通用应用程序环境的接口,它可以用于任何类型的应用程序,无论是Web应用程序还是非Web应用程序。
  • ConfigurableWebEnvironment:这个接口是专门为Web应用程序设计的,用于配置和管理Web应用程序的运行环境,它扩展了ConfigurableEnvironment接口,添加了一些与Web环境相关的特性。然而,需要注意的是,在较新版本的Spring框架中(如Spring 5及以后),ConfigurableWebEnvironment接口实际上已经被废弃,而推荐使用ConfigurableEnvironment来处理Web和非Web环境的配置,但在旧版本的Spring中,这个接口仍然存在并用于区分Web和非Web环境。

2、提供的功能

  • ConfigurableEnvironment:这个接口提供了一组方法来配置和管理应用程序的环境属性,可以通过它添加、删除或修改属性源,并定制属性的检索顺序,此外,它还提供了访问和修改系统属性、环境变量等功能。
  • ConfigurableWebEnvironment:除了继承自ConfigurableEnvironment的所有功能外,这个接口还提供了对Servlet上下文初始化参数的访问,这是Web应用程序特有的功能,允许在Web应用程序的运行环境中访问和修改Servlet上下文的初始化参数,由于该接口在较新版本的Spring中已被废弃,因此在实际开发中可能不会直接使用它

代码案例

下面代码演示了几个使用频率较高的Environment代码案例。

StandardEnvironment案例

下面是一个简单的Java代码示例,演示了如何使用org.springframework.core.env.StandardEnvironment类。

这个示例创建了一个StandardEnvironment实例,并通过它访问了系统属性和环境变量。

import org.springframework.core.env.StandardEnvironment;  

public class StandardEnvironmentExample {
   
     

    public static void main(String[] args) {
   
     
        // 创建一个StandardEnvironment实例  
        StandardEnvironment environment = new StandardEnvironment();  

        // 获取系统属性"java.version"  
        String javaVersion = environment.getSystemProperties().getProperty("java.version");  
        System.out.println("Java Version: " + javaVersion); // 输出Java版本信息  

        // 获取环境变量"PATH"(注意:环境变量的名称可能因操作系统而异)  
        String pathVariable = environment.getSystemEnvironment().get("PATH");  
        // 在Windows上,PATH环境变量的分隔符是";",在Unix/Linux上是":"  
        String pathSeparator = System.getProperty("path.separator");  
        if (pathVariable != null) {
   
     
            System.out.println("PATH Environment Variable (first entry): " + pathVariable.split(pathSeparator)[0]);  
            // 输出PATH环境变量的第一个条目(根据路径分隔符分割后)  
        } else {
   
     
            System.out.println("PATH Environment Variable is not set.");  
        }  

        // 尝试获取一个不存在的系统属性或环境变量将返回null  
        String nonExistentProperty = environment.getSystemProperties().getProperty("non.existent.property");  
        System.out.println("Non-Existent Property: " + nonExistentProperty); // 输出null或未定义属性的信息  
    }  
}

在这段代码中,创建了一个StandardEnvironment的实例,然后,使用getSystemProperties()方法获取系统属性,并通过getProperty()方法获取特定的属性(在这个例子中是"java.version")。

类似地,使用getSystemEnvironment()方法获取环境变量,并通过get()方法获取特定的环境变量(在这个例子中是"PATH")。请注意,环境变量的名称和可用性可能因操作系统而异。

注意,如果是非Web应用程序则推荐使用StandardEnvironment,如果是Web应用程序,则推荐使用StandardServletEnvironment

ConfigurableEnvironment案例

下面是一个使用org.springframework.core.env.ConfigurableEnvironment类的Java代码示例。

在这个示例中,创建一个ConfigurableEnvironment实例,并向其添加自定义的属性源。=,然后,将演示如何从环境中检索这些属性。

import org.springframework.core.env.ConfigurableEnvironment;  
import org.springframework.core.env.MapPropertySource;  
import org.springframework.core.env.Environment;  

import java.util.HashMap;  
import java.util.Map;  

public class ConfigurableEnvironmentExample {
   
     

    public static void main(String[] args) {
   
     
        // 创建一个ConfigurableEnvironment实例  
        ConfigurableEnvironment environment = new ConfigurableEnvironment();  

        // 创建一个包含自定义属性的Map  
        Map<String, Object> customProperties = new HashMap<>();  
        customProperties.put("custom.property.one", "Value One");  
        customProperties.put("custom.property.two", "Value Two");  

        // 创建一个属性源,并命名为"customProperties"  
        MapPropertySource customPropertySource = new MapPropertySource("customProperties", customProperties);  

        // 将自定义属性源添加到环境中  
        environment.getPropertySources().addLast(customPropertySource);  

        // 从环境中检索自定义属性并打印它们  
        String propertyOne = environment.getProperty("custom.property.one");  
        String propertyTwo = environment.getProperty("custom.property.two");  

        System.out.println("Custom Property One: " + propertyOne); // 输出: Custom Property One: Value One  
        System.out.println("Custom Property Two: " + propertyTwo); // 输出: Custom Property Two: Value Two  

        // 尝试获取一个不存在的属性将返回null  
        String nonExistentProperty = environment.getProperty("non.existent.property");  
        System.out.println("Non-Existent Property: " + nonExistentProperty); // 输出: Non-Existent Property: null  
    }  
}

在这段代码中,创建了一个ConfigurableEnvironment实例,然后,创建了一个包含自定义属性的Map,并使用这个Map创建了一个MapPropertySource实例,将这个自定义属性源命名为"customProperties",并将其添加到环境的属性源列表的末尾。

接着,使用environment.getProperty()方法从环境中检索自定义属性,并将它们打印到控制台。最后,尝试获取一个不存在的属性,以演示当属性不存在时返回null的情况。

关注我,每天学习互联网编程技术 - 程序员古德

END!
END!
END!

往期回顾

精品文章

Spring揭秘:Aware接口应用场景及实现原理!

Spring揭秘:@import注解应用场景及实现原理!

Spring揭秘:ImportBeanDefinitionRegistrar应用场景及实现原理!

Java并发基础:原子类之AtomicMarkableReference全面解析!

Java并发基础:concurrent Flow API全面解析

相关文章
|
24天前
|
XML Java 数据格式
探索Spring之利剑:ApplicationContext接口
本文深入介绍了Spring框架中的核心接口ApplicationContext,解释了其作为应用容器的功能,包括事件发布、国际化支持等,并通过基于XML和注解的配置示例展示了如何使用ApplicationContext管理Bean实例。
48 6
|
12天前
|
人工智能 前端开发 Java
Spring AI Alibaba + 通义千问,开发AI应用如此简单!!!
本文介绍了如何使用Spring AI Alibaba开发一个简单的AI对话应用。通过引入`spring-ai-alibaba-starter`依赖和配置API密钥,结合Spring Boot项目,只需几行代码即可实现与AI模型的交互。具体步骤包括创建Spring Boot项目、编写Controller处理对话请求以及前端页面展示对话内容。此外,文章还介绍了如何通过添加对话记忆功能,使AI能够理解上下文并进行连贯对话。最后,总结了Spring AI为Java开发者带来的便利,简化了AI应用的开发流程。
203 0
|
1月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
57 14
|
2月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
241 12
基于开源框架Spring AI Alibaba快速构建Java应用
|
1月前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
1月前
|
XML 前端开发 安全
Spring MVC:深入理解与应用实践
Spring MVC是Spring框架提供的一个用于构建Web应用程序的Model-View-Controller(MVC)实现。它通过分离业务逻辑、数据、显示来组织代码,使得Web应用程序的开发变得更加简洁和高效。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring MVC,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
67 2
|
2月前
|
JSON 安全 算法
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
79 8
|
2月前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
57 1
|
2月前
|
JavaScript Java 关系型数据库
Spring事务失效的8种场景
本文总结了使用 @Transactional 注解时事务可能失效的几种情况,包括数据库引擎不支持事务、类未被 Spring 管理、方法非 public、自身调用、未配置事务管理器、设置为不支持事务、异常未抛出及异常类型不匹配等。针对这些情况,文章提供了相应的解决建议,帮助开发者排查和解决事务不生效的问题。
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
124 2