上篇文章主要说了Aware接口:
如何吧spring底层组件赋值到自定义组件里呢,可以实现xxxAware接口,比如实现ApplicationContextAware接口,可以获取到applicationContext。这些都是由xxxAwareProcessor后置处理器处理的,如ApplicationContextAwareProcessor,先创建bean之后,后置处理器处理吧对应的数据赋值。
这篇文章主要说@Profile:
文章分为两个部分,第一部分,数据源环境的搭建。第二部分,@Profile能根据开发环境和测试环境,家在不同的数据源,所有第二部分,如何通过spring提供的@Profile注解,根据我们当前的开发环境,动态的激活和切换一系列组件。
一、数据源环境搭建
先贴一份本文目录
首先创建myConfigProfile类,创建dataSource.properties配置文件,用我们之前学到过的@PropertySource注解指定加载的配置文件,用三种不同的方法获取到配置文件里面的值,都是我们之前学到过得。
1)、@Value普通获取值
2)、在方法参数上用@Value获取值
3)、实现EmbeddedValueResolverAware接口,解析器获取运行环境里面的值。
配置文件如下:
dataName=root
dataPassword=root
data.driver.class=com.mysql.jdbc.Driver
新的配置类如下:
/**
* @Profile:根据我们的当前环境,动态的激活和切换一系列组件。
* 如test环境用test配置,dev环境用dev配置
*
* @author keying
*/
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
public class MyConfigProfile implements EmbeddedValueResolverAware {
@Value("${dataName}")
private String user;
private String driverClass;
@Bean("testDataSource")
public DataSource test(@Value("${dataPassword}") String password) throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
comboPooledDataSource.setDriverClass(driverClass);
return comboPooledDataSource;
}
@Bean("devDataSource")
public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
comboPooledDataSource.setDriverClass(driverClass);
return comboPooledDataSource;
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
//配置文件信息放入环境里,解析器从环境信息中获取
this.driverClass = resolver.resolveStringValue("${data.driver.class}");
}
}
/**
* @author keying
*/
public class IOCTestProfile {
@Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
MyConfigProfile.class);
//根据类型获取数据源
String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
for(String string:strings){
System.out.println(string);
}
}
}
通过junitTest打印可以看到,可以获取我们的两个数据源。本文演示是链接mysql数据库两个不同的database,同学请先在电脑上安装mysql数据库并建立好test和dev两个数据库,不知道安装mysql的自行百度。
二、@Profile注解使用
* 1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。
* 2、改为加载test数据源:
* 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test
* 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。
* 用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。
* 3)没有配置@Profile的bean,不管在哪个环境都能加载。
*
* @Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。
/**
* @author keying
*/
public class IOCTestProfile {
/**
* 1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。
* 2、改为加载test数据源:
* 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test
* 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。
* 用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。
* 3)没有配置@Profile的bean,不管在哪个环境都能加载。
*
* @Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。
*/
@Test
public void test() {
//第一步创建applicationContext对象
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
);
//第二部设置需要激活的环境
ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
configurableEnvironment.setActiveProfiles("test");
//第三部注册主配置类
applicationContext.register(MyConfigProfile.class);
//第四部刷新启动
applicationContext.refresh();
//根据类型获取数据源
String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
for (String string : strings) {
System.out.println(string);
}
Yellow yellow = applicationContext.getBean(Yellow.class);
System.out.println(yellow);
applicationContext.close();
}
}
/**
* @author keying
* @Profile:根据我们的当前环境,动态的激活和切换一系列组件。 如test环境用test配置,dev环境用dev配置
*/
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
//@Profile("test")
public class MyConfigProfile implements EmbeddedValueResolverAware {
@Value("${dataName}")
private String user;
private String driverClass;
@Bean
public Yellow yellow(){
return new Yellow();
}
@Profile("test")
@Bean("testDataSource")
public DataSource test(@Value("${dataPassword}") String password) throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
comboPooledDataSource.setDriverClass(driverClass);
return comboPooledDataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
comboPooledDataSource.setDriverClass(driverClass);
return comboPooledDataSource;
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
//配置文件信息放入环境里,解析器从环境信息中获取
this.driverClass = resolver.resolveStringValue("${data.driver.class}");
}
}
从打印可以看出来,yellow在设置了test环境之后,还是 能打印出来,并且profile注解配置了dev的就打印不出来。
问:@Confitional注解和@Profile注解都能用在类上,并且都是不满足就不加载,有什么不同?
@Profile是修改系统环境的数据,需要在ioc容器refresh()之前设置,所以不能用有参构造加载配置类。
@Conditional则是在可以获取到环境里面的值,在进行过滤判断,如获取当前运行环境或者系统,进行过滤。