在一些场景中,有可能会遇到这种情况,在生产环境,灰度环境,开发环境和测试环境希望IOC中注入的Bean具有不同的特性。通常在paas环境中或者有配置中心的分布式开发环境,通过统一的集中配置可以完成这种需求,本篇就简单谈谈如果单单使用springframework如何实现这样的多环境配置。
@Profile
这个注解是常用的环境区分的工具。结合@Configuration,它为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。
@Profile("default")
@Bean("test")
public DataSource testDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("dev")
@Bean("dev")
public DataSource devDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("master")
@Bean("master")
public DataSource masterDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Test
public void test01() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
//1. 创建一个applicationContext
//2. 设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev","master");
//3. 注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4. 启动刷新容器
applicationContext.refresh();
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
System.out.println(Arrays.toString(beanNamesForType));
applicationContext.close();
}
@Test
public void test02() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
System.out.println(Arrays.toString(beanNamesForType));
applicationContext.close();
}
或者在测试类中
@RunWith(SpringJUnit4ClassRunner.class)//创建spring应用上下文
@ContextConfiguration(classes= DataSourceConfig.class)//加载配置类
@ActiveProfiles("dev")
public class ProfileTest {
@Autowired
private DataSource dataSource;
@Test
public void sheetTest(){
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
List<String> query = jdbc.query("select * from customer", new RowMapper<String>() {
@Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getLong("id") + ":" + rs.getString("customer_name");
}
});
// [19:知识追寻者, 20:知识追寻者, 21:知识追寻者, 22:知识追寻者, 23:知识追寻者]
System.out.println(query);
}
}
或者Java命令中添加参数:
-Dspring.profiles.active="profile1,profile2"
@Conditional
@Profile时间是是@Conditonal的实现。
Spring Boot除了提供通用的@Condition注解外,还提供了一些开箱即用的条件注解,方便开发者在开发时直接使用。比如:
- ·@ConditionOnBean:在ApplicationContext中存在指定类型的Bean时启用。
- ·@ConditionOnMissingBean:在ApplicationContext中不存在指定类型的Bean时启用。
- ·@ConditionOnClass:在classpath下存在指定类时启用。
- ·@ConditionOnMissingClass:在classpath下缺少指定类时启用。
- ·@ConditionOnProperties:当存在指定属性配置时启用。
- ·@ConditionOnResource:当存在指定资源时启用。
- ·@ConditionOnWebApplication:当应用是一个Web应用时启用。