Spring系列.Environment接口

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} 這種形式配置默認值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章