在实际开发中,我们可能会遇到这样一种情况,开发、测试和生产中所使用的bean有所不同,比如DataSource,虽然起的功能一样,但在不同的环境中,我可能想要使用不同的DataSource,难道需要我们换个环境就直接修改代码吗?
当然不是,Spring已经为我们提供了解决方案.
1. spring profile
在3.1版本时,spring引入了bean profile的功能,profile功能就是将不同的bean定义到profile中,在部署运行时,确保对应的profile处于激活状态即可.被激活的profile中的bean就会被创建到spring中,而未被激活的profile中的bean就不会被创建到spring中.(没有被定义在profile中的bean不受影响)
1.1 Java配置profile
在Java配置中,我们可以使用@Profile注解指定某个bean属于哪一个profile,例如:
@Configuration
@Profile("dev")
public class SpringConfig {
@Bean
.....
}
上例中,@Profile("dev") 应用在类级别上,它会告诉spring这个配置类中的bean只有在dev profile激活时才会创建,如果dev profile没有激活,则该配置类中的bean将不会被创建.
在spring3.1中,@Profile注解只能修饰类,但是在3.2版本中,@Profile就可以用于方法上,例如:
@Configuration
public class SpringConfig {
@Bean
@Profile("dev")
public A getA(){
return new A();
}
@Bean
@Profile("prod")
public B getB(){
return new B();
}
}
在这个例子中,A只会在dev profile激活时被创建,B只会在prod profile激活时被创建.
1.2 XML配置profile
在XML中,我们可以通过<beans>的profile属性来配置profile bean.
<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-3.1.xsd"
profile="development">
<bean id="person" class="com.hmkcode.vo.Person">
<property name="id" value="1" />
<property name="name" value="dev-person" />
</beans>
或者你也可以通过在<beans>中嵌套<beans>来定义profile:
<?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-3.1.xsd">
<beans profile="development">
<bean id="person" class="com.hmkcode.vo.Person">
<property name="id" value="1" />
<property name="name" value="dev-person" />
</bean>
</beans>
<beans profile="production">
<bean id="person" class="com.hmkcode.vo.Person">
<property name="id" value="2" />
<property name="name" value="pro-person" />
</bean>
</beans>
</beans>
1.3 激活profile
说了两种配置的办法,我们还需要知道怎么激活profile,spring在确定激活哪个profile时,需要依赖两个独立的属性,spring.profiles.active和spring.profiles.default,如果设置了spring.profiles.active,那么它的值就会被用来确定哪个profile是激活的,如果没有设置,则spring会去查找spring.profiles.default的值,如果两个值均没有设置,则没有profile是激活的,则所有profile下的bean都不会被创建.
有多种方式来设置这两个属性:
1.作为DispatcherServlet的初始化参数
2.作为Web应用的上下文参数
3.作为JNDI条目
4.作为环境变量
5.作为JVM的系统属性
6.在集成测试类上,使用@AutiveProfiles注解配置
2. 条件化bean
现在假设我们有这样一种需求,我们希望某个bean在满足某种条件的情况下才会被创建,这时我们就可以使用注解@Conditional去修饰bean.
@Configuration
public class SpringConfig {
@Bean
@Conditional(MyCondition.class)
public A getA() {
return new A();
}
}
class MyCondition implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}
我们可以看到,@Conditional中是一个类,这个类必须要实现Condition接口,该接口中有一个matches方法,该方法若返回true,则表示该bean可以被创建,若是返回false,则表示该bean不被创建.至于matches方法中的参数应用,这里不做过多的介绍.