很多情况下,我们需要在不同的环境下装配不同的Bean,比如数据库,测试环境我们想用嵌入式数据库,开发环境我们想用mysql,线上环境我们想用oracle,总不能每次上线都要改代码吧。
Spring提供给了我们@Profile来根据我们的环境确定我们要装配哪儿种Bean。
JavaConfig中使用Profile
直接上代码:
@Configuration
public class DataSourceConfig {
@Bean(destroyMethod = "shutdown")
@Profile("dev")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
@Bean
@Profile("prod")
public DataSource jndiDataSource() {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}
}
在本例中,如果是prod环境,则使用myDs数据库,如果是dev则使用嵌入式数据库。
XML中使用Profile
<beans profile="dev">
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:schema.sql" />
<jdbc:script location="classpath:test-data.sql" />
</jdbc:embedded-database>
</beans>
<beans profile="prod">
<jee:jndi-lookup id="dataSource"
lazy-init="true"
jndi-name="jdbc/myDatabase"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
</beans>
激活Profile
通过这两种方式我们可以根据自己的环境来装配不同的Bean,那么Spring是怎么激活Profile呢,也就是说Spring怎么知道我们的环境是prod还是dev的呢?
Spring通过spring.profiles.active和spring.profiles.default来激活对应的属性。
- 如果spring.profiles.active配置了值,会按照spring.profiles.active配置的值来激活Profile
- 如果spring.profiles.active没有配置值,会按照spring.profiles.default来激活对应的Bean。
如果spring.profiles.default也没有配置,则Spring只会激活没有使用@Profile注解标注的Bean。
设置spring.profiles.active和spring.profiles.default
那么我们怎么设置这个两个属性呢?
有下面几种方式:作为DispatcherServlet的初始参数
- 作为Web应用的上下文
- 作为JNDI条目
- 作为环境变量
- 作为JVM的系统属性
- 在继承测试类上,使用@ActiveProfiles注解设置
我还是推荐使用环境变量来激活这两个值,比较环境变量不是经常变动的,可以保证不用来回修改配置文件导致的问题。