First we look at spring official explanation of this document annotation:
The
@Profile
annotation allows you to indicate that a component is eligible for registration when one or more specified profiles are active
This notation according to the current environment, the dynamic range of the activation and switching component
Combined with some knowledge before doing an example, when we developed, may in the development of connections is the development environment of the database, when the test connection test environment, the production environment is connected is the production database, used in different environments the database is different, how to dynamically switch data sources injected it?
Configuration class to explain
First, look at the configuration class MainConfigProfile
class
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;
import com.atguigu.bean.Yellow;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* Profile:
* Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
*
* 开发环境、测试环境、生产环境;
* 数据源:(/A)(/B)(/C);
*
*
* @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
*
* 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
* 2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
* 3)、没有标注环境标识的bean在,任何环境下都是加载的;
*/
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
private StringValueResolver valueResolver;
private String driverClass;
@Bean
public Yellow yellow(){
return new Yellow();
}
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); // 测试库
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud"); // 开发库
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515"); // 生产库
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
this.valueResolver = resolver;
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
}
}
In the configuration class, we injected three Bean, corresponding to the test environment, development environment, production environment.
We know that inject data sources need Four Diamond: user, password, driver, url.
Note: Here, the three environments that are not connected to the same database, as we are here only to distinguish url. Url in each environment is different.
The other three parameters, we are disposed in the path of the class db.properties
as follows
db.user=root
db.password=123456
db.driverClass=com.mysql.jdbc.Driver
Prior knowledge combined with my study here, into a different use db.properties
values
The use of the resource file is loaded, this usage can be found: the Spring and @PropertySource is used @Value property assignment
@PropertySource("classpath:/dbconfig.properties")
That is how
dataSource.setUser(user);
dataSource.setPassword(pwd);
These two methods of assigning it?
First we construct a
private String user;
Attribute, then the attributes @Value("${db.user}")
and then
dataSource.setUser(user);
To get the value.
Secondly it,
public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{...}
We add a parameter in the method, before adding a parameter @Value("${db.password}")
can from the resource file db.properties
to get the value, assigned to this parameter
Summary: The above is @Value usage, refer to the link above
Were here, we put it another way, to get the resource file driverClass,
We can implement EmbeddedValueResolverAware
interfaces spring there are many aware interface is available to way we use the underlying functionality of the spring.
Here EmbeddedValueResolverAware
is the value resolver, implement the interface, which is an abstract method of achieving
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
this.valueResolver = resolver;
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
}
When the container starts, this method will be called,
We define an attribute for the value of the received process parameter, i.e.StringValueResolver resolver
private StringValueResolver valueResolver;
Then parse
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
And assigned to the property driverClass our custom. So this property would get the value of the resource file
And above relationship @Profile not much, but good review
In addition, we are still in the configuration class defined called yellow
the bean.
Test, and activate the corresponding environment
First, we all do not join @Profile
comment
Test, watch the console output, which we called a test method
package com.atguigu.test;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.bean.Yellow;
import com.atguigu.config.MainConfigOfProfile;
public class IOCTest_Profile {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
}
mainConfigOfProfile
yellow
testDataSource
devDataSource
prodDataSource
Class contains the configuration can be seen that all of the bean itself ioc are injected into the vessel.
Now open all @Profile comments
For example, we are now dev
under development environment that is, how to activate only @Bean("devDataSource")
the component of it?
We write a test class
package com.atguigu.test;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.bean.Yellow;
import com.atguigu.config.MainConfigOfProfile;
public class IOCTest_Profile {
//1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
@SuppressWarnings("resource")
//2、代码的方式激活某种环境;
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//1、创建一个applicationContext
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev"); // 这里可以写多个值,
//3、注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh();
String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String string : namesForType) {
System.out.println(string);
}
Yellow bean = applicationContext.getBean(Yellow.class);
System.out.println(bean);
applicationContext.close();
// AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
// String[] definitionNames = applicationContext.getBeanDefinitionNames();
// for (String name : definitionNames) {
// System.out.println(name);
// }
}
}
Print Console:
devDataSource
com.atguigu.bean.Yellow@27ce24aa // 没有被@Profile修饰。
Observation can be found, indeed, only development environment bean is injected ioc container,
There is another way to activate @Profile comment.
Test Method 1:
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
Then run the process, but parameters need to add virtual machines running time. We need to activate the back = environment, a plurality of values separated by commas.
-Dspring.profiles.active=test
Print it out:
mainConfigOfProfile
yellow
testDataSource //测试环境被注入
@Profile annotation at the class,
Remain unchanged configuration class, we add on the configuration class@Profile("prod")
We run the test method (preceded mentioned), and not the console output, which represents the configuration of the bean class have not been injected into the container,
May be thinking this way: @Profile notes marked on the class, if you do not specify an activation of the environment, the natural configuration of the entire class will not be loaded, configured class Bean (even if, as Yellow, not @Profile notes), nor It will be injected into the container,
In the same way that we have to correct the environment after it is activated? (How to activate the environment, refer to the previous article)
Console printout
mainConfigOfProfile
yellow
prodDataSource
This is obviously what we expected is the same.
Tips
If the environment is not activated, it @Profile("default")
will be activated, that is, the default is the default setting.