美文网首页
0x03.Environment

0x03.Environment

作者: 0x70e8 | 来源:发表于2018-07-18 23:33 被阅读0次

    [TOC]

    Environment是集成在容器中的抽象,它为应用程序环境的两个关键方面建模:概要文件(Profile)和属性(Properties)。

    一个Profile是一个命名的、逻辑的bean定义组,只有在给定的Profile处于活动状态时才会在容器中注册。可以将bean分配给一个Profile,不管它是在XML中定义还是通过注释。与Profile相关的环境对象的作用是确定哪些Profile(如果有的话)当前处于活动状态,以及默认情况下哪些Profile(如果有的话)应该处于活动状态。

    Properties在几乎所有的应用程序中都扮演着重要的角色,并且可以来自各种来源:属性文件、JVM系统属性、系统环境变量、JNDI、servlet上下文参数、ad-hoc属性对象、映射等等。与属性相关的环境对象的作用是为用户提供方便的服务接口,用于配置属性源和解析属性。

    Environment集成了profile和properties,profile的用意接近环境,properties则是环境中的一些属性值,profile决定了当前处于哪一个环境(使用哪一种bean定义的容器),这样可以在构建工程时根据不同的阶段使用不同的环境,而不用频繁改动配置来适应不同的阶段。如开发、测试和生产环境使用的是不同的数据库配置,通过profile来对应不同的环境,无需将一个配置文件改来改去。

    profile

    Bean定义profile是核心容器中的一种机制,它允许在不同的环境中注册不同的Bean。

    对应profile定义bean

    @Profile

    • @Bean上使用
    @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");
        }
    }
    

    对于@Bean方法上的@Profile,可以应用一个特殊的场景:对于重载了相同Java方法名的@Bean方法(类似于构造函数重载)的情况,需要在所有重载方法上始终声明@Profile条件。如果条件不一致,则只有重载方法中的第一个声明的条件才生效。因此,不能使用@Profile来选择具有特定参数签名的重载方法;同一bean的所有工厂方法之间的解析遵循Spring在创建时的构造函数解析算法。

    • @Configuration类上使用@Profile
    @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");
        }
    }
    

    在@Configuration类上使用@Profile注解,则其内部所有的@Bean方法都遵循profile的规则,包括在类中@Import导入的config。

    也可以使用@Profile作为元注解来定义一个注解:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Profile("production")
    public @interface Production {
    }
    

    这个注解@Production和@Profile("production")意义是一样的。

    XML定义profile

    • beans标签上定义
    <beans profile="development"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"
        xsi:schemaLocation="...">
    
        <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>
    
    • bean标签上定义
    <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

    激活一个概要文件可以通过几种方式完成,但是最简单的方法是使用通过ApplicationContext可获得的Environment API进行编程:

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

    此外,还可以通过系统环境变量、JVM系统属性、web.xml中的servlet上下文参数来指定spring.profiles.active属性,甚至作为JNDI中的一个条目来声明性地激活配置文件。

    default Profile

    @Profile("default")指定默认支持的profile。

    Properties

    PropertySource

    Spring使用PropertySource对象来抽象环境中的properties。

        ApplicationContext ctx = new GenericApplicationContext();
        Environment env = ctx.getEnvironment();
    

    Spring提供了env的标准实现:org.springframework.core.env.StandardEnvironment
    它内部集成了系统属性和系统环境变量;

    @Override
        protected void customizePropertySources(MutablePropertySources propertySources) {
            propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
            propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
        }
    
    • 添加属性到env中
        ConfigurableApplicationContext ctx = new GenericApplicationContext();
        MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
        sources.addFirst(new MyPropertySource());
    

    @PropertySource

    The @PropertySource annotation provides a convenient and declarative mechanism for adding a PropertySource to Spring’s Environment.

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

    参考资料

    [1] Spring Framework Reference Documentation

    相关文章

      网友评论

          本文标题:0x03.Environment

          本文链接:https://www.haomeiwen.com/subject/ttnjpftx.html