Spring装配Bean ---环境相关的bean
看Spring实战(第4版)笔记
存疑:激活profile
在开发软件的时候,有一个很大的挑战就是将应用程序从一个环境迁移到另外一个环境 。
有些bean就是在不同的环境需要不同的配置,也就是环境相关的bean。比如数据库配置、加密算法以及与外部系统的集成 都是在跨环境部署时可能会发生变化。
要解决这个问题,有一个种方式 是在单独的配置类(XML配置文件)中配置每个bean,然后在构建阶段确定要将哪一个配置编译到可部署的应用中。 这种方式的问题 是 要为每种环境重新构建应用。但是重新构建可能会引入bug
Spring为环境相关的bean所提供的解决方案 是 根据环境决定该创建哪个bean和不创建哪个bean。
它不是在构建时作出决策,而是等到运行时再来确定。这样呢,就可以保证同一个部署单元(比如war文件)能适用于所有的环境,没有必要重新构建。
1.JavaConfig配置 profile bean----@Profile注解
配置profile bean 总共有4种方式:(1)为每个环境创建一个配置类,JavaConfig配置 @Profile注解在类级别(2)JavaConfig配置 @Profile注解在方法级别, (3) 为每个环境都创建一个profile XML文件 profile属性 用在xml配置文件根配置上 <beans profile="">(4)xml配置文件 profile属性bean定义上<beans profile="">。
在JavaConfig配置中 @Profile注解 如果配置在类级别上,那就是告诉Spring 这个配置类里所有的bean都是 特定 profile激活时才会创建。如果 特定 profile没有激活,这类配置类 所有的@Bean注解的方法都会被忽略。Spring3.2开始 @Profile注解 也可以放在方法级别。
以下的例子 这里有两个bean,类型都是 DataSource,并且ID都是dataSource。但是在运行时,只会创建一个bean,这取决于处于激活状态的是哪个profile。
public class DateSource {
}
在类级别上使用@Profile注解 配置dev环境的bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class DevProfileConfig {
@Bean
public DateSource devDateSource() {
System.out.println("this is devDateSource ");
return new DateSource();
}
}
在类级别上使用@Profile注解 配置prd环境的bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("prd")
public class PrdProfileConfig {
@Bean
public DateSource prdDateSource() {
System.out.println(" this is prdDateSource");
return new DateSource();
}
}
或者在方法级别上使用@Profile注解 在同一个配置类定义dev和prd环境的bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
@Configuration
public class SystemConfig {
@Bean
@Profile("dev")
public DateSource devDateSource() {
System.out.println(" this is devDateSource for method @Profile");
return new DateSource();
}
@Bean
@Profile("prd")
public DateSource prdDateSource() {
System.out.println(" this is prdDateSource for method @Profile");
return new DateSource();
}
}
2.激活profile ---- @ActiveProfiles注解
Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和spring.profiles.default。
如果设置了spring.profiles.active属性的话,那么它的值就会用来确定哪个profile是激活的。
但如果没有设置spring.profiles.active属性的话,那Spring将会查找spring.profiles.default的值。
如果spring.profiles.active和spring.profiles.default均没有设置的话,那就没有激活的profile,因此只会创建那些没有定义在
profile中的bean。
有多种方式来设置这两个属性:
作为DispatcherServlet的初始化参数;
作为Web应用的上下文参数;
作为JNDI条目;
作为环境变量;
作为JVM的系统属性;
在集成测试类上,使用@ActiveProfiles注解设置。
测试 上述JavaConfig配置的 环境相关的bean
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@Configuration
@ActiveProfiles("dev")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { DevProfileConfig.class, PrdProfileConfig.class })
public class Test {
@Autowired
private DateSource DateSource;
@org.junit.Test
public void test() {
System.out.println("nothing");
}
}