慢慢来比较快,虚心学技术
1.为什么需要profile?
实际开发中,生产环境和开发环境通常都不会是同一个,最明显的例子就是,生产环境(正式环境)的数据库和开发环境的数据库一般都是不一样的。那么为了方便配置的转换,Spring提供了profile关键字进行统一的环境配置,通过profile配置我们可以快速的切换整个应用的环境,而不需要从代码层面进行重新构建
那么,使用profile的目的是为了更方便的配置不同的环境,指定某些具体的类或组件的作用域
注:每个bean或组件都有默认的作用域default,如果没有限定作用域,则这些bean都会被装配,如果指定了作用域,则只有处在相应作用域(环境)中时才会被装配
2.怎么配置profile?
JavaConfig显式装配或者自动装配可以通过注解@Profile进行环境限制,比如:
Ⅰ、自动化装配,我们将类DataSource的作用域限定为只有当环境为“prod”才被装配,结合@Component注解和@Profile注解实现
代码1.1
@Component
@Profile("prod")
public class DataSource {
/**
* 定义名称
*/
private String name;
public DataSource(){
super();
}
public DataSource(String name){
this.name = name;
}
}
Ⅱ、JavaConfig显式配置,有两种实现方式
- 第一种:在指定多个配置类,在配置类上指定作用域,其内所定义的所有Bean只能在该作用域下被装配,进行环境统一配置
代码1.2
//1.创建一个配置类DevConfig,并将其作用域设置为dev,则其内定义的Bean只有在环境为dev的时候才可以被装载
@Configuration
@Profile(value = "dev")
public class DevConfig {
//定义一个name属性为Dev DataSource的Bean
@Bean
public DataSource dataSource(){
return new DataSource("Dev DataSource");
}
}
//2.创建一个配置类ProdConfig,并将其作用域设置为prod,则其内定义的Bean只有在环境为prod的时候才可以被装载
@Configuration
@Profile(value = "prod")
public class ProdConfig {
//定义一个name属性为Dev DataSource的Bean
@Bean
public DataSource dataSource(){
return new DataSource("Prod DataSource");
}
}
//3.创建一个默认配置类,当系统未指定系统环境时,将默认使用该配置
@Configuration
public class DefaultConfig {
@Bean
public DataSource dataSource(){
return new DataSource("Default DataSource");
}
}
//4.创建一个统一配置类SystemConfig,并将三个配置类引入,因为各自定义了作用域(DefaultConfig未明文指定),所以引入并不会导致冲突
@Configuration
@Import({DevConfig.class,ProdConfig.class,DefaultConfig.class})
public class SystemConfig {}
- 第二种:除了在类上使用@Profile指定类作用域之外,@Profile还可以在方法上使用,在JavaConfig结合@Bean进行装配环境的限制
代码1.3
@Configuration
public class SystemConfig {
@Bean
@Profile("dev")//当系统环境为dev的时候,使用该Bean方法进行装配
public DataSource devDataSource(){
return new DataSource("Dev DataSource");
}
@Bean
@Profile("prod")//当系统环境为prod的时候,使用该Bean方法进行装配
public DataSource prodDataSource(){
return new DataSource("Prod DataSource");
}
@Bean//默认装配
public DataSource defaultDataSource(){
return new DataSource("Default DataSource");
}
}
Ⅲ、XML配置Profile,和JavaConfig类似也有两种方式
- 第一种:为每一个配置文件的<beans>配置Profile,只有在固定对应环境下配置文件才会生效(比较常用)
代码1.4
//1、创建配置文件DevConfig.xml,并在<beans>节点设置profile属性为dev,只有在环境为dev的时候本配置文件生效
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="dev"
>
<bean class="com.my.spring.bean.DataSource" name="dataSource">
<constructor-arg name="name" value="Dev DataSource"></constructor-arg>
</bean>
</beans>
//2、创建配置文件ProdConfig.xml,并在<beans>节点设置profile属性为prod,只有在环境为prod的时候本配置文件生效
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="prod"
>
<bean class="com.my.spring.bean.DataSource" name="dataSource">
<constructor-arg name="name" value="Prod DataSource"></constructor-arg>
</bean>
</beans>
//3、创建配置文件DefaultConfig.xml,默认加载
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.my.spring.bean.DataSource" name="dataSource">
<constructor-arg name="name" value="Default DataSource"></constructor-arg>
</bean>
</beans>
//4、创建系统配置文件,将上述三个配置文件引入,因为限定了环境,所以并不会冲突
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="DefaultConfig.xml"/>
<import resource="DevConfig.xml"/>
<import resource="ProdConfig.xml"/>
</beans>
- 第二种:在同一个配置文件中指定不同的<beans>设定profile属性,所包裹的bean只有在指定环境下才会被装配
代码1.5
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<description>Spring配置文件</description>
<beans>
<bean id="dataSource" name="default" class="com.my.spring.bean.DataSource">
<constructor-arg name="name" value="Default DataSource"></constructor-arg>
</bean>
</beans>
<beans profile="dev">
<bean id="dataSource" name = "dev" class="com.my.spring.bean.DataSource">
<constructor-arg name="name" value="Dev DataSource"></constructor-arg>
</bean>
</beans>
<beans profile="prod">
<bean id="dataSource" name="prod" class="com.my.spring.bean.DataSource">
<constructor-arg name="name" value="Prod DataSource"></constructor-arg>
</bean>
</beans>
</beans>
3、如何激活profile?
如上述配置每个配置文件或者JavaConfig,Bean等的profile属性后,如何设定一个系统所处的环境呢?
Spring提供了多种方式:
作为 DispatcherServlet 的初始化参数;
作为 Web 应用的上下文参数;
作为 JNDI 条目;
作为环境变量;
作为 JVM 的系统属性;
在集成测试类上,使用 @ActiveProfiles 注解设置;
- 此处先了解@ActiveProfiles注解方式
在上一章中,我们了解到,Spring测试使用@RunWith(SpringJUnit4ClassRunner.class)和@ContextConfiguration注解进行应用上下文注入测试,在测试中我们可以通过结合@ActiveProfiles注解进行测试环境的配置,具体代码如下:
以自动化装配模式为例:
上述代码1.1中指定DataSource只有在prod环境下才会被装载,故在测试中将系统环境分别指定为prod和dev测试DataSource的Bean是否会装配
代码1.6
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {ComponentConfig.class})
@ActiveProfiles("prod")//指定系统环境为prod
public class AppComponentTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testGetBean(){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanDefinitionNames){
System.out.println(beanName);
}
}
}
测试结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
componentConfig
dataSource //dataSource被装配
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {ComponentConfig.class})
@ActiveProfiles("dev")//指定系统环境为dev
public class AppComponentTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testGetBean(){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanDefinitionNames){
System.out.println(beanName);
}
}
}
//dataSource未被装配
测试结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
componentConfig
再以JavaConfig显式装配为例,设定不同的profile测试获取到的dataSource是否一致,以代码1.3作为系统配置:
代码1.7
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {SystemConfig.class})
@ActiveProfiles("prod")//指定系统配置环境为prod
public class AppConfigTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testGetBean(){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanDefinitionNames){
System.out.println(beanName);
}
}
}
测试结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
systemConfig
prodDataSource //证明获取的是prod环境的dataSource
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {SystemConfig.class})
@ActiveProfiles("dev")//指定系统配置环境为dev
public class AppConfigTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testGetBean(){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanDefinitionNames){
System.out.println(beanName);
}
}
}
测试结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
systemConfig
devDataSource //证明获取的是dev环境的dataSource
- 由于未了解到网络模块,所以web配置方式暂不赘述
网友评论