自动装配 05 @Profile环境搭建
和condition
相似
@Profile:Spring为我们提供的可以根据当前环境动态的激活和切换一系列组件的功能 也可以根据环境切换数据源
dev
test
prov
@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定的时候任何环境下都能注册这个组件
- 加了环境标识的bean 只有这个环境被激活的时候才能注册到容器中。
- 写在配置类上,只有是指定的环境的时候,整个配置类中的所有配置才能开始生效
- 没有标注环境标识的bean,任何环境下都是加载的。默认是
default
修改运行环境的几种方式
- 使用命令行动态参数:在虚拟机参数位置加载
-Dspring.profiles.active=[运行环境]
:-Dspring.profiles.active=test
- 手动代码设置
- 获取ApplicationContext :注意要使用无参方式获取,否则刷新之后还是没有注入的状态(具体可查看源码分析)
- 设置需要激活的环境
- 注册主配置类
- 启动刷新容器
代码测试
配置类
/**
* 用于测试数据源和运行环境
* 使用了多种方式设置参数
*/
@PropertySource("classpath:/dbConfig.properties")
@Configuration
public class MainConfig4Profile implements EmbeddedValueResolverAware {
public MainConfig4Profile() {
}
@Value("${db.user}")
private String user;
// 用于EmbeddedValueResolverAware接口测试
private String driverClass;
@Profile("prov")
@Bean("provDataSouce")
public DataSource dataSource4Prov() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/sb_anno_prov?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8");
// 加载驱动的时候会抛异常
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource;
}
@Profile("dev")
@Bean("devDataSouce")
public DataSource dataSource4Dev() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("${db.user}");
dataSource.setPassword("${db.password}");
dataSource.setJdbcUrl("${db.user}");
dataSource.setDriverClass("${db.driverClass}");
return dataSource;
}
@Profile("test")
@Bean("testDataSouce")
public DataSource dataSource4Test(@Value("${db.password}") String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/sb_anno_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.driverClass = resolver.resolveStringValue("${db.driverClass}");
System.out.println("解析后的driverClass " + driverClass);
}
}
dbConfig.properties
db.user=root
db.password=
db.driverClass=com.mysql.jdbc.Driver
pom.xml
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- 注意版本问题,本地安装的是5.几的版本,而springboot默认导入的是最新的,需要手动指定版本号-->
<version>5.1.46</version>
<scope>runtime</scope>
</dependency>
测试
@Test
void profileTest(){
//配置类测试
System.out.println("准备创建容器");
// 1. 获取ApplicationContext 注意要使用无参构造器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
System.out.println("容器创建完毕");
// 2. 设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test","dev");
// 3. 注册配置类
applicationContext.register(MainConfig4Profile.class);
// 4. 启动刷新容器
applicationContext.refresh();
System.out.println("容器刷新完毕");
// 获取bean
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String name : beanNamesForType) {
System.out.println("当前环境下注入的bean" + name);
}
// 关闭容器
applicationContext.close();
System.out.println("容器已关闭");
}
运行结果:
AnnotationConfigApplicationContext.java部分源码(无参构造):
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotationConfigApplicationContext.java部分源码(有参构造):
/**
* 有参方式调用的时候,最后的refresh相当于没有设置
*/
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}