本博客demo源码地址
https://github.com/suchahaerkang/spring-annotation.git
1 @Profile的作用
@Profile的作用:切换不同的环境,可以动态的将不同的组件注册到容器中去
现在有这么一个需求,我们都知道我们在开发项目的时候一般都会有开发(dev),测试(test)和生产(prod)环境。每个环境的数据源都不一样,我们现在怎么实现只用切换环境,相应的组件将动态的注册到容器呢?
下面开始写代码
首先向项目中引入数据源的包,这里我们就用c3p0。然后引入一个mysql的驱动包
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
写个配置类,将容器中注册三个组件(开发数据源 devDataSource,测试数据源testDataSource,生成数据源prodDataSource)
/**
* @description:
* @author: sukang
* @date: 2020-03-08 12:40
*/
@PropertySource(value = {"classpath:/db.properties"})
@Configuration
public class MainConfigOfProfile {
@Value("${database.username}")
private String userName;
@Value("${database.password}")
private String password;
@Value("${database.driver}")
private String driver;
@Bean("devDataSource")
public DataSource dataSourceOfDev() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("http://localhost:3306/dev");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
@Bean("testDataSource")
public DataSource dataSourceOfTest() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("http://localhost:3306/test");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
@Bean("prodDataSource")
public DataSource dataSourceOfProd() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("http://localhost:3306/prod");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
}
默认情况下这三个数据源都将会注册到容器中去
写个测试用例
@Test
public void test01(){
//创建容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
//获取容器中组件为DataSource的所有名字
String[] beanNames = applicationContext.getBeanNamesForType(DataSource.class);
for (String name : beanNames) {
System.out.println(name);
}
}
运行结果
测试结果可以看出,三个数据源都注册进容器了,但是这不是我们想要的,我们是想要在什么样的环境就注册什么样的数据源。下面我们通过@Profile注解来实现这个功能,加上@Profile注解的配置类
/**
* @description:
* @author: sukang
* @date: 2020-03-08 12:40
*/
@PropertySource(value = {"classpath:/db.properties"})
@Configuration
public class MainConfigOfProfile {
@Value("${database.username}")
private String userName;
@Value("${database.password}")
private String password;
@Value("${database.driver}")
private String driver;
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceOfDev() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceOfTest() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceOfProd() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");
dataSource.setUser(userName);
dataSource.setPassword(password);
dataSource.setDriverClass(driver);
return dataSource;
}
}
在配置类中加上@Profile之后,还没有效果,必须在启动容器的时候激活某个环境才能生效
2 激活环境的两种方式
1)使用命令行动态参数,在虚拟机参数位置加上'-Dspring.profiles.active=dev'
运行结果
2)另外一种方法是通过写代码的方式
@Test
public void test02(){
//创建容器调用无参构造函数
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//激活测试环境
applicationContext.getEnvironment().setActiveProfiles("test");
//注册MainConfigOfProfile组件
applicationContext.register(MainConfigOfProfile.class);
//刷新容器
applicationContext.refresh();
//获取容器中组件为DataSource的所有名字
String[] beanNames = applicationContext.getBeanNamesForType(DataSource.class);
for (String name : beanNames) {
System.out.println(name);
}
}
运行结果