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} 這種形式配置預設值。