Environment 接口介紹
在 Spring 中,Environment 接口主要管理應用程序兩個方面的內容:profile 和 properties。
profile 可以簡單的等同於環境,比如說平時項目中常見的環境有開發(dev)、測試(stg)和生產(prod),Spring 啟動的時候可以設置激活具體的環境。當然,這個 profile 我們還可以為其賦予很多含義,這個主要看你的業務。比如說,你開發的軟件會交付給客戶A,也會交付給客戶B,那么這個 profile 也可以定義成客戶的含義。
properties 是配置,配置的來源有很多,可以是配置文件、JVM 的參數、系統的環境變量、JNDI、Sevlet Contxet 參數以及 Map 對象等,使用 Environment 接口,可以方便的獲取這些配置。
Bean Definition Profiles
使用 @Profile
Spring 容器可以根據不同的 profile 配置不同的 Bean。這個特性可以幫助你實現很多靈活的功能,比如:
- 開發環境使用內存數據庫,測試和生產環境才使用關系型數據庫,比如 Mysql 和 Oracle 等
- 交互給客戶 A 的軟件使用 A 特性,交付給客戶 B 的軟件使用 B 特性
@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 非常適合在兩個環境下,Bean 的定義完全不一樣的情況,如果兩個 Bean 的定義是一樣的,只是一些參數不一樣的話,我們完全可以使用配置文件的方式實現。
@Profile 注解后面的表達式可以是一個簡單的字符串,也可以是一個邏輯運算符。@Profile 支持如下的邏輯運算符。
- !: A logical “not” of the profile
- &: A logical “and” of the profiles
- |: A logical “or” of the profiles
說明:
If a
@Configuration
class is marked with@Profile
, all of the@Bean
methods and@Import
annotations associated with that class are bypassed unless one or more of the specified profiles are active. If a@Component
or@Configuration
class is marked with@Profile({"p1", "p2"})
, that class is not registered or processed unless profiles 'p1' or 'p2' have been activated.
使用 xml 方式配置
<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
1. API 方式
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
// 設置激活的 profile
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();
2. 命令行方式
-Dspring.profiles.active="profile1,profile2"
3. 配置文件方式
spring:
profiles:
active: dev
默認的 profile
Spring 默認的 profile 是 default
,可以通過 Environment 的 API 進行修改。
PropertySource 接口
PropertySource 接口是對任何形式的 key-value 鍵值對的抽象。
@PropertySource
@PropertySource 這個注解的作用是將配置文件中的鍵值對放入Environment。這個注解的作用和傳統配置方式中的 context:place-hold一致。
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
經過上面這樣的配置,我們就可以使用 ${key} 這種形式來取變量的值。有時如果我們沒配置 key 的值,Spring 會拋異常。這時我們可以使用 ${key:defaultvalue} 這種形式配置默認值。