javascript
Spring5参考指南:Environment
文章目錄
- Profiles
- PropertySource
- 使用@PropertySource
Spring的Environment接口有兩個(gè)關(guān)鍵的作用: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是一個(gè)Bean的邏輯分組,只有在給定的配置文件處于活動(dòng)狀態(tài)時(shí),才會(huì)在容器中注冊(cè)。
Properties主要用來(lái)從各種源:屬性文件、JVM系統(tǒng)屬性、系統(tǒng)環(huán)境變量、JNDI、servlet上下文參數(shù)、特殊屬性對(duì)象、映射對(duì)象等讀取屬性的定義。
Profiles
在開(kāi)發(fā)中,我們可以需要在不同的環(huán)境定義不同的配置,例如:
- 在開(kāi)發(fā)中處理內(nèi)存中的數(shù)據(jù)源,而不是在QA或生產(chǎn)中從JNDI中查找相同的數(shù)據(jù)源。
- 僅在將應(yīng)用程序部署到性能環(huán)境中時(shí)注冊(cè)監(jiān)控基礎(chǔ)結(jié)構(gòu)。
- 為客戶(hù)A和客戶(hù)B部署注冊(cè)定制的bean實(shí)現(xiàn)。
假如我們有兩個(gè)數(shù)據(jù)源,一個(gè)是在測(cè)試環(huán)境使用,一個(gè)是在線上環(huán)境使用,則可以通過(guò)profile來(lái)指定不同的環(huán)境。如下所示:
@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里面的表達(dá)式可以是簡(jiǎn)單的字符串,也可以支持運(yùn)算符,如:
- ! 邏輯非
- & 邏輯與
- | 邏輯或
可以將@Profile用作元注解,以創(chuàng)建自定義組合注解。以下示例定義了一個(gè)自定義的@Production注解,您可以將其用作@Profile(“production”)的替換:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Profile("production") public @Interface Production { }@Profile也可以用在方法級(jí)別用來(lái)包含一個(gè)特殊的bean或者配置類(lèi)。如下所示:
@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,但是怎么激活他們?
激活一個(gè)概要文件可以用幾種方法完成,但最簡(jiǎn)單的方法是通過(guò)應(yīng)用程序上下文提供的環(huán)境API以編程方式完成。以下示例顯示了如何執(zhí)行此操作:
public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();ctx.getEnvironment().setActiveProfiles("development");ctx.register(AppConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);ctx.refresh();}此外,還可以通過(guò)spring.profiles.active屬性聲明性地激活概要文件,該屬性可以通過(guò)系統(tǒng)環(huán)境變量、jvm系統(tǒng)屬性、web.xml中的servlet上下文參數(shù)指定,甚至可以作為JNDI中的條目指定.
如下所示:
-Dspring.profiles.active=“profile1,profile2”
你也可以同時(shí)激活多個(gè)pofile
ctx.getEnvironment().setActiveProfiles(“profile1”, “profile2”);
默認(rèn)Profile
默認(rèn)的Profile表示該P(yáng)rofile默認(rèn)被激活,如下所示:
@Configuration @Profile("default") public class DefaultDataConfig {@Beanpublic DataSource dataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:com/bank/config/sql/schema.sql").build();} }如果沒(méi)有Profile被激活,那么dataSource就會(huì)被創(chuàng)建,你可以看成創(chuàng)建bean的默認(rèn)方式。如果其他的Profile被激活了,那么默認(rèn)的Profile就不會(huì)被使用。
您可以在環(huán)境中使用SetDefaultProfiles()更改默認(rèn)profile的名稱(chēng),或者聲明性地使用spring.profiles.default屬性更改默認(rèn)概要文件的名稱(chēng)。
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查詢(xún)是否定義了my-property屬性,這里的StandardEnvironment定義了兩組PropertySource對(duì)象進(jìn)行查詢(xún),
/** 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";一個(gè)表示一組JVM系統(tǒng)屬性(System.GetProperties()),另一個(gè)表示一組系統(tǒng)環(huán)境變量(System.getEnv())。
對(duì)于常見(jiàn)的StandardServletEnvironment,property的查詢(xún)優(yōu)先級(jí)如下:
- ServletConfig參數(shù)(如果適用-例如,對(duì)于DispatcherServlet上下文)
- ServletContext參數(shù)(web.xml context-param 項(xiàng))
- JNDI環(huán)境變量(Java:COMP/Env/條目)
- JVM系統(tǒng)屬性(-d命令行參數(shù))
- JVM系統(tǒng)環(huán)境(操作系統(tǒng)環(huán)境變量)
使用@PropertySource
@PropertySource注解提供了方便和聲明式的機(jī)制為Spring的添加PropertySource.
下面的@Configuration類(lèi)使用@PropertySource 來(lái)調(diào)用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資源位置中存在的任何$…占位符將根據(jù)已針對(duì)環(huán)境注冊(cè)的屬性源集進(jìn)行解析,如下示例所示:
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")假設(shè)my.placeholder存在于已注冊(cè)的某個(gè)屬性源中(例如,系統(tǒng)屬性或環(huán)境變量),則將占位符解析為相應(yīng)的值。如果不是,則default/path用作默認(rèn)值。如果未指定默認(rèn)值且無(wú)法解析屬性,則將引發(fā)IllegalArgumentException。
本節(jié)的例子可以參考Environment
更多精彩內(nèi)容且看:
- 區(qū)塊鏈從入門(mén)到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
- Spring Boot 2.X系列教程:七天從無(wú)到有掌握Spring Boot-持續(xù)更新
- Spring 5.X系列教程:滿(mǎn)足你對(duì)Spring5的一切想象-持續(xù)更新
- java程序員從小工到專(zhuān)家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程
更多教程請(qǐng)參考flydean的博客
總結(jié)
以上是生活随笔為你收集整理的Spring5参考指南:Environment的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring5参考指南:JSR 330标
- 下一篇: Spring5参考指南:事件Event