Spring5参考指南:Environment

作者:

本文已参与掘金创做者训练营第三期「高产更文」赛道,详情查看:掘力计划|创做者训练营第三期正在进行,「写」出我的影响力。html

Spring的Environment接口有两个关键的做用:1. Profile, 2.properties。能够看下该接口的定义:java

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...)}. *

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 not 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:git

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 getProperty(String key, Class 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 getProperty(String key, Class 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 getRequiredProperty(String key, Class 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的逻辑分组,只有在给定的配置文件处于活动状态时,才会在容器中注册。github

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

Profiles

在开发中,咱们能够须要在不一样的环境定义不一样的配置,例如:spring

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

假如咱们有两个数据源,一个是在测试环境使用,一个是在线上环境使用,则能够经过profile来指定不一样的环境。以下所示:sql

@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”)的替换:markdown

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

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

@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属性,以下所示:

复制代码

激活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的博客

the end

免责声明:本文内容均来自互联网,但不代表简明教程的观点和立场.

已有 2164 次赞