[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;
}
}
网友评论