spring Environment


Environment
環境在容器中是一個抽象的集合,是指應用環境的2個方面: profiles和 properties.

profile
配置是一個被命名的,bean定義的邏輯組,這些bean只有在給定的profile配置激活時才會注冊到容器。不管是XML還是注解,Beans都有可能指派給profile配置。Environment環境對象的作用,對於profiles配置來說,它能決定當前激活的是哪個profile配置,和哪個profile是默認。

在所有的應用中,Properties屬性扮演一個非常重要的角色,可能來源於一下源碼變量:properties文件,JVM properties,system環境變量,JNDI, servlet context parameters上下文參數,專門的Properties對象,Maps等等。Environment對象的作用,對於properties來說,是提供給用戶方便的服務接口,方便撰寫配置、方便解析配置。

bean定義profiles是核心容器內的一種機制,該機制能在不同環境中注冊不同的bean。環境的意思是,為不同的用戶做不同的事兒,該功能在很多場景中都非常有用,包括:開發期使用內存數據源,在QA或者產品上則使用來自JNDI的相同的數據源開發期使用監控組件,當部署以后則關閉監控組件,是應用更高效為用戶各自注冊自定義bean實現.

考慮一個實際應用中的場景,現在需要一個DataSource。開測試環境中,這樣配置:

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("my-schema.sql")
        .addScript("my-test-data.sql")
        .build();
}

  

現在想一想,如何將應用部署到QA或者生產環境,假設生產環境中使用的JNDI。我們的dataSource bean看起來像這樣:

@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}

  

我們需要在某些上下文環境中使用某些bean,在其他環境中則不用這些bean。你也許會說,你需要在場景A中注冊一組bean定義,在場景B中注冊另外一組。先看看我們如何修改配置來完成此需求。
@Profile注解的作用,是在一個或者多個指定profiles激活的情況下,注冊某個組件。使用上面的樣例,重寫dataSource配置:

@Configuration
@Profile("dev")
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

要修改配置,我們仍然需要指定要激活哪個文件。如果現在運行上面的樣例應用,它會拋異常NoSuchBeanDefinitionException,因為容器找不到dataSourcebean。

有多種方式激活配置,但是最直接的方式是編程式的方式使用ApplicationContext API

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

  

此外,還可以使用spring.profiles.active激活配置,該屬性可以配置在系統環境變量、JVM系統屬性、web.xml
中JNDI中的servlet context上下文參數
注意配置文件不是單選;可能會同時激活多個配置文件,編程式的使用方法setActiveProfiles(),該方法接收String數組參數,也就是多個配置文件名

ctx.getEnvironment().setActiveProfiles("profile1", "profile2");
//聲明式的使用spring.profiles.active ,值可以為逗號分隔的配置文件名列表, -Dspring.profiles.active="profile1,profile2"

 

如果沒有任何profile配置被激活,默認的profile將會激活。
默認profile配置文件可以更改,通過環境變量的setDefaultProfiles方法,或者是聲明的spring.profiles.default屬性值

Spring的環境抽象提供了用於檢索一系列的property sources屬性配置文件。

ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
boolean containsFoo = env.containsProperty("foo");
System.out.println("Does my environment contain the ''foo'' property? " + containsFoo);

  

在上面的片段中,通過較高層次方式檢索SPring是否在當前環境中定義了foo property屬性。為了檢索該屬性,環境對象在一組PropertySource對象中執行檢索。PropertySource是key-value鍵值對配置文件的抽象,Spring的StandardEnvironment
配置了2個PropertySource對象.其一是JVM系統properties(System.getProperties()),另一個是一組系統環境變量System.getEnv()。

@PropertySource注解提供了一個方便的方式,用於增加一個PropertySource到Spring的環境中: 給定一個文件"app.properties"包含了key/value鍵值對testbean.name=myTestBean,下面的@Configuration類使用了@PropertySource
,使用這種方式調用testBean.getName()將會返回myTestBean。

@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;
    }
}

  

轉自:https://www.jianshu.com/p/49e950b0b008


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM