javascript
Spring5参考指南:Environment
文章目錄
- Profiles
- PropertySource
- 使用@PropertySource
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)}*/@Deprecatedboolean 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)*/@NullableString 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 {@Beanpublic 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 {@Beanpublic 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 {@AutowiredEnvironment env;@Beanpublic 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
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
更多教程請參考flydean的博客
總結
以上是生活随笔為你收集整理的Spring5参考指南:Environment的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring5参考指南:JSR 330标
- 下一篇: Spring5参考指南:事件Event