Spring的Environment接口有两个关键的作用:1. Profile, 2.properties。可以看下该接口的定义:

public interface Environment extends PropertyResolver {

	/**
* Return the set of profiles explicitly made active for this environment. Profiles
* are used for creating logical groupings of bean definitions to be registered
* conditionally, for example based on deployment environment. Profiles can be
* activated by setting {@linkplain AbstractEnvironment#ACTIVE_PROFILES_PROPERTY_NAME
* "spring.profiles.active"} as a system property or by calling
* {@link ConfigurableEnvironment#setActiveProfiles(String...)}.
* <p>If no profiles have explicitly been specified as active, then any
* {@linkplain #getDefaultProfiles() default profiles} will automatically be activated.
* @see #getDefaultProfiles
* @see ConfigurableEnvironment#setActiveProfiles
* @see AbstractEnvironment#ACTIVE_PROFILES_PROPERTY_NAME
*/
String[] getActiveProfiles(); /**
* Return the set of profiles to be active by default when no active profiles have
* been set explicitly.
* @see #getActiveProfiles
* @see ConfigurableEnvironment#setDefaultProfiles
* @see AbstractEnvironment#DEFAULT_PROFILES_PROPERTY_NAME
*/
String[] getDefaultProfiles(); /**
* Return whether one or more of the given profiles is active or, in the case of no
* explicit active profiles, whether one or more of the given profiles is included in
* the set of default profiles. If a profile begins with '!' the logic is inverted,
* i.e. the method will return {@code true} if the given profile is <em>not</em> active.
* For example, {@code env.acceptsProfiles("p1", "!p2")} will return {@code true} if
* profile 'p1' is active or 'p2' is not active.
* @throws IllegalArgumentException if called with zero arguments
* or if any profile is {@code null}, empty, or whitespace only
* @see #getActiveProfiles
* @see #getDefaultProfiles
* @see #acceptsProfiles(Profiles)
* @deprecated as of 5.1 in favor of {@link #acceptsProfiles(Profiles)}
*/
@Deprecated
boolean acceptsProfiles(String... profiles); /**
* Return whether the {@linkplain #getActiveProfiles() active profiles}
* match the given {@link Profiles} predicate.
*/
boolean acceptsProfiles(Profiles profiles); }

它继承了PropertyResolver:

public interface PropertyResolver {

	/**
* Return whether the given property key is available for resolution,
* i.e. if the value for the given key is not {@code null}.
*/
boolean containsProperty(String key); /**
* Return the property value associated with the given key,
* or {@code null} if the key cannot be resolved.
* @param key the property name to resolve
* @see #getProperty(String, String)
* @see #getProperty(String, Class)
* @see #getRequiredProperty(String)
*/
@Nullable
String getProperty(String key); /**
* Return the property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
* @param key the property name to resolve
* @param defaultValue the default value to return if no value is found
* @see #getRequiredProperty(String)
* @see #getProperty(String, Class)
*/
String getProperty(String key, String defaultValue); /**
* Return the property value associated with the given key,
* or {@code null} if the key cannot be resolved.
* @param key the property name to resolve
* @param targetType the expected type of the property value
* @see #getRequiredProperty(String, Class)
*/
@Nullable
<T> T getProperty(String key, Class<T> targetType); /**
* Return the property value associated with the given key,
* or {@code defaultValue} if the key cannot be resolved.
* @param key the property name to resolve
* @param targetType the expected type of the property value
* @param defaultValue the default value to return if no value is found
* @see #getRequiredProperty(String, Class)
*/
<T> T getProperty(String key, Class<T> targetType, T defaultValue); /**
* Return the property value associated with the given key (never {@code null}).
* @throws IllegalStateException if the key cannot be resolved
* @see #getRequiredProperty(String, Class)
*/
String getRequiredProperty(String key) throws IllegalStateException; /**
* Return the property value associated with the given key, converted to the given
* targetType (never {@code null}).
* @throws IllegalStateException if the given key cannot be resolved
*/
<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException; /**
* Resolve ${...} placeholders in the given text, replacing them with corresponding
* property values as resolved by {@link #getProperty}. Unresolvable placeholders with
* no default value are ignored and passed through unchanged.
* @param text the String to resolve
* @return the resolved String (never {@code null})
* @throws IllegalArgumentException if given text is {@code null}
* @see #resolveRequiredPlaceholders
* @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String)
*/
String resolvePlaceholders(String text); /**
* Resolve ${...} placeholders in the given text, replacing them with corresponding
* property values as resolved by {@link #getProperty}. Unresolvable placeholders with
* no default value will cause an IllegalArgumentException to be thrown.
* @return the resolved String (never {@code null})
* @throws IllegalArgumentException if given text is {@code null}
* or if any placeholders are unresolvable
* @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String, boolean)
*/
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException; }

Profile是一个Bean的逻辑分组,只有在给定的配置文件处于活动状态时,才会在容器中注册。

Properties主要用来从各种源:属性文件、JVM系统属性、系统环境变量、JNDI、servlet上下文参数、特殊属性对象、映射对象等读取属性的定义。

Profiles

在开发中,我们可以需要在不同的环境定义不同的配置,例如:

  • 在开发中处理内存中的数据源,而不是在QA或生产中从JNDI中查找相同的数据源。
  • 仅在将应用程序部署到性能环境中时注册监控基础结构。
  • 为客户A和客户B部署注册定制的bean实现。

假如我们有两个数据源,一个是在测试环境使用,一个是在线上环境使用,则可以通过profile来指定不同的环境。如下所示:

@Configuration
@Profile("development")
public class StandaloneDataConfig { @Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
@Configuration
@Profile("production")
public class JndiDataConfig { @Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}

@Profile里面的表达式可以是简单的字符串,也可以支持运算符,如:

  • ! 逻辑非
  • & 逻辑与
  • | 逻辑或

可以将@Profile用作元注解,以创建自定义组合注解。以下示例定义了一个自定义的@Production注解,您可以将其用作@Profile(“production”)的替换:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("production")
public @Interface Production {
}

@Profile也可以用在方法级别用来包含一个特殊的bean或者配置类。如下所示:

@Configuration
public class AppConfig { @Bean("dataSource")
@Profile("development")
public DataSource standaloneDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
} @Bean("dataSource")
@Profile("production")
public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}

Profiles在XML中使用

可以在XML中使用profile属性,如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="..."> <!-- other bean definitions --> <beans profile="development">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans> <beans profile="production">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>
</beans>

激活Profile

上面我们定义好了Profile,但是怎么激活他们?

激活一个概要文件可以用几种方法完成,但最简单的方法是通过应用程序上下文提供的环境API以编程方式完成。以下示例显示了如何执行此操作:

    public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(AppConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();
}

此外,还可以通过spring.profiles.active属性声明性地激活概要文件,该属性可以通过系统环境变量、jvm系统属性、web.xml中的servlet上下文参数指定,甚至可以作为JNDI中的条目指定.

如下所示:

-Dspring.profiles.active=“profile1,profile2”

你也可以同时激活多个pofile

ctx.getEnvironment().setActiveProfiles(“profile1”, “profile2”);

默认Profile

默认的Profile表示该Profile默认被激活,如下所示:

@Configuration
@Profile("default")
public class DefaultDataConfig { @Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}

如果没有Profile被激活,那么dataSource就会被创建,你可以看成创建bean的默认方式。如果其他的Profile被激活了,那么默认的Profile就不会被使用。

您可以在环境中使用SetDefaultProfiles()更改默认profile的名称,或者声明性地使用spring.profiles.default属性更改默认概要文件的名称。

PropertySource

下面是使用PropertySource的例子:

    public static void main(String[] args) {
ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
boolean containsMyProperty = env.containsProperty("my-property");
System.out.println("Does my environment contain the 'my-property' property? " + containsMyProperty);
}

这里Spring查询是否定义了my-property属性,这里的StandardEnvironment定义了两组PropertySource对象进行查询,

	/** System environment property source name: {@value}. */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment"; /** JVM system properties property source name: {@value}. */
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

一个表示一组JVM系统属性(System.GetProperties()),另一个表示一组系统环境变量(System.getEnv())。

对于常见的StandardServletEnvironment,property的查询优先级如下:

  • ServletConfig参数(如果适用-例如,对于DispatcherServlet上下文)
  • ServletContext参数(web.xml context-param 项)
  • JNDI环境变量(Java:COMP/Env/条目)
  • JVM系统属性(-d命令行参数)
  • JVM系统环境(操作系统环境变量)

使用@PropertySource

@PropertySource注解提供了方便和声明式的机制为Spring的添加PropertySource.

下面的@Configuration类使用@PropertySource 来调用testBean.getName() 返回 myTestBean:

@Configuration
@PropertySource("classpath:app.properties")
public class PropertiesConfig { @Autowired
Environment env; @Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}

@Propertysource资源位置中存在的任何$…占位符将根据已针对环境注册的属性源集进行解析,如下示例所示:

@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")

假设my.placeholder存在于已注册的某个属性源中(例如,系统属性或环境变量),则将占位符解析为相应的值。如果不是,则default/path用作默认值。如果未指定默认值且无法解析属性,则将引发IllegalArgumentException。

本节的例子可以参考Environment

更多教程请参考flydean的博客

Spring5参考指南:Environment的更多相关文章

  1. Spring5参考指南:IOC容器

    文章目录 为什么使用Spring5 什么是IOC容器 配置元数据 实例化容器 XML嵌套 groovy bean定义DSL 使用容器 最近在翻译Spring Framework Documentati ...

  2. Spring5参考指南:基于注解的容器配置

    文章目录 @Required @Autowired @primary @Qualifier 泛型 @Resource @PostConstruct和@PreDestroy Spring的容器配置可以有 ...

  3. Spring5参考指南:容器扩展

    文章目录 BeanPostProcessor自定义bean BeanFactoryPostProcessor自定义配置元数据 使用FactoryBean自定义实例化逻辑 Spring提供了一系列的接口 ...

  4. Spring5参考指南:Bean的生命周期管理

    文章目录 Spring Bean 的生命周期回调 总结生命周期机制 startup和Shutdown回调 优雅的关闭Spring IoC容器 Spring Bean 的生命周期回调 Spring中的B ...

  5. Spring5参考指南:Bean作用域

    文章目录 Bean作用域简介 Singleton作用域 Prototype作用域 Singleton Beans 中依赖 Prototype-bean web 作用域 Request scope Se ...

  6. Spring5参考指南:依赖注入

    文章目录 依赖注入 依赖注入的配置详解 depends-on lazy-init 自动装载 方法注入 依赖注入 依赖注入就是在Spring创建Bean的时候,去实例化该Bean构造函数所需的参数,或者 ...

  7. Spring5参考指南:Bean的创建

    文章目录 Spring容器中的Bean Bean的命名 Bean的实例化 Spring容器中的Bean Bean在Spring中就是一个业务组件,我们通过创建各种Bean来完成最终的业务逻辑功能. 在 ...

  8. Spring5参考指南:AspectJ高级编程之Configurable

    文章目录 遇到的问题 @Configurable 原理 重要配置 遇到的问题 前面的文章我们讲到了在Spring中使用Aspect.但是Aspect的都是Spring管理的Bean. 现在有一个问题, ...

  9. Spring5参考指南:AOP代理

    文章目录 AOP代理 AOP Proxies原理 AOP代理 通常来说Spring AOP有两种代理方式,一种默认的JDK代理,只能代理接口,一种是CGLIB代理,可以代理具体的类对象. Spring ...

随机推荐

  1. jmeter实现接口关联的两种方式:正则表达式提取器和json提取器看这篇就够了

    一.前言在开展接口测试或者是接口面试的过程中,我们会发现很多接口需要依赖前面的接口,需要我们动态从前面的接口返回中提取数据,也就是我们通常说的关联. 关联通俗来讲就是把上一次请求的返回内容中的部分截取 ...

  2. 学编程这么久,还傻傻分不清什么是方法(method),什么是函数(function)?

    在编程语言中有两个很基础的概念,即方法(method)和函数(function).如果达到了编程初级/入门级水平,那么你肯定在心中已有了初步的答案. 也许在你心中已有答案了 除去入参.返回值.匿名函数 ...

  3. 国内 Java 开发者必备的两个装备,你配置上了么?

    虽然目前越来越多的国产优秀技术产品走出了国门,但是对于众领域的开发者来说,依然对于国外的各种基础资源依赖还是非常的强.所以,一些网络基本技能一直都是我们需要掌握的,但是速度与稳定性问题一直也都有困扰着 ...

  4. 《Three.js 入门指南》3.0 - 代码构建的最基本结构。

    3.0 代码构建的最基本结构 说明: 我们必需首先知道,Three.js 的一些入门级概念: 我们需要知道,OpenGL 是一套三维实现的标准,为什么说是标准,因为它是跨平台,跨语言的.甚至CAD以及 ...

  5. c期末笔记(4)

    未命名易错点 1.0<y<10 在c语言中,0<y<10不是一个正确的表达式,应该利用逻辑运算符替换(y>0&&y<10或者!(y<=0||y ...

  6. linux安装常用软件和查询基本信息

                                                                          linux安装常用软件和查询基本信息 1. 安装常用软件 [ ...

  7. Debian Bug report logs - #724721 zsh: Tab completion error with vi

    Hi Ludovic, Ludovic Lebègue wrote: > While using zsh shell trying to autocomplete with tab key di ...

  8. Windows 手动安装 Apache24 web服务器

    文章更新于:2020-02-18 按照惯例,需要的文件附上链接放在文首 文件名:httpd-2.4.41-o111c-x64-vc15-r2.7z 文件大小:6.1MB 下载链接:https://ww ...

  9. 大O表示法是什么?

    1.什么是大O表示法: 1.在算法描述中,我们用这种方式来描述计算机算法的效率. 2.在计算机中,这种粗略的量度叫做 "大O" 表示法. 3.在具体的情境中,利用大O表示法来描述具 ...

  10. go 错误处理与测试

    Go 没有像 Java 和 .NET 那样的 try/catch 异常机制:不能执行抛异常操作.但是有一套 defer-panic-and-recover 机制(参见 13.2-13.3 节). Go ...