环境与profile
为了使一些 Bean 在特定情况注册而引入机制,若是使用不同的 XML 配置要为每种环境重新构建,也可能引入 BUG,使用 profile 则不会,因为 不需要重新构建
配置profile bean
- Java 配置中使用@profile 指定 Bean 属于哪个profile
- Spring 3.2中可以将@profile 放在方法上,所以可以将不同 profile 的 Bean 放在一个配置类中
配置profile
在xml中配置profile
<beans profile="">
…
</beans>
可以在根元素中定义profile,也可以嵌套定义,把所有的profile bean定义在同一个xml文件中
激活profile
决定激活哪一个profile取决于spring.profiles.actice和spring.profiles.default
设置该属性的方式
- 作为dispacherServlet的初始化参数
- 作为web应用的上下文参数
- 作为jndi条目
- 作为环境变量
- 作为jvm的系统属性
- 在继承测试类上使用@ActiceProfiles注解设置
条件化的bean
- @conditional注解
示例:
@conditional
@bean
public magicbean magicBean(){
return new magicBean();
}
@conditional中给定一个class,由这个class来判断是否构建该bean
设置给它的class要实现condition接口
public interface Condition(){
boolean matches(ConditionContext ctxt,
AnnotatedTypeMetadata metadata);
}
通过ConditionContext,我们可以做到如下几点:
- 借助getRegistry()返回的BeanDefinitionRegistry检查bean定义; -
- 借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是 否存在,甚至探查bean的属性; -
- 借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是 什么; 读取并探查getResourceLoader()返回的ResourceLoader所加载的资源; -
-
借助getClassLoader()返回的ClassLoader加载并检查类是否存在,
AnnotatedTypeMetadata则能够让我们检查带有@Bean注解的方法上还有什么其他的注 解。像ConditionContext一样,AnnotatedTypeMetadata也是一个接口。它如下所示: -
借助isAnnotated()方法,我们能够判断带有@Bean注解的方法是不是还有其他特定的注 解。借助其他的那些方法,我们能够检查@Bean注解的方法上其他注解的属性。
非常有意思的是 - 从Spring 4开始,@Profile注解进行了重构,使其基于@Conditional和 Condition实现。
//@file的实现
@Retention(TetentionPolicy.RUNTIME)
@Target({ElementTYPE,ElementType.METHOD})
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile{
String[] value();
}
注意: @Profile本身也使用了@Conditional注解,并且引用ProfileCondition作为Condition实现。如下所示,ProfileCondition实现 了Condition接口,并且在做出决策的过程中,考虑到了ConditionContext和AnnotatedTypeMetadata中的多个因素。
处理自动装配的歧义性
如果有多个bean可以适配的化自动装配将会失败,所以当歧义性出现,spring提供了多种方式解决
1. 标识首选bean
- @primary注解
在首选bean上进行注解,在只有一个首选bean时消除歧义性
2. 限定自动装配的bean
- @Qualifier注解
- 直接给qualifier注解传入beanID ,但是会造成紧耦合
- 自定义限定符