例子:
@bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean(){
return new MagicBean();
}
@Conditional注解中的class可以是任意实现了Condition接口的类型,Condition接口如下:
public interface Condition{
boolean matches(ConditionContext ctxt,AnnotatedTypeMetadata metadata);
}
实现了Condition接口的类型例子:
public class MagicExistsCondition implements Condition{
public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata){
Environment env = context.getEnvironment();
return env.containsProperty("magic");
}
}
ConditionContext接口大致如下:
public interface ConditoinContext{
BeanDefinitionRegistry getRegistry(); //用于检查bean定义
ConfigurableListableBeanFactory getBeanFactory(); //检查bean是否存在以及bean属性
Environment getEnvironment(); //检查环境变量是否存在以及其值
ResourceLoader getResourceLoader(); //读取并探查ResourceLoader所家在的资源
ClassLoader getClassLoader(); //加载并检查类是否存在
}
AnnotatedTypeMetadata用于检查带有@Bean注解的方法上还有什么其他的注解,AnnotatedTypeMetadata接口如下:
public interface AnnotatedTypeMetadata{
boolean isAnnotated(String annotationType); //判断是否还有其他特定的注解
Map<String,Object> getAnnotationAttributes(String annotationType); //其他注解的属性
Map<String,Object> getAnnotationAttributes(String annotationType,boolean classValuesAsString);
MultiValueMap<String,Object> getAllAnnotationAttributes(String annotationType);
MultiValueMap<String,Object> getAllAnnotationAttributes(String annotationType,boolean classValuesAsString);
}
Spring4之后@Profile注解进行了重构,使其基于@Conditional和Condition实现,下面是@Profile注解的实现:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documentd
@Conditional(ProfileCondition.class)
public @interface Profile{
String[] value();
}
class ProfileCondition implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
if(context.getEnvironment() != null){
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if(attrs != null)
for(Object value : attrs.get("value")){
if(context.getEnvironment().acceptsProfiles(((String[])value))){
return true;
}
}
return false;
}
}
return true;
}
}
ProfileCondition通过AnnotatedTypeMetadata得到了用于@Profile注解的所有属性,借助该信息,它会明确地检查value属性,该属性包含了bean的profile名称,然后根据通过ConditionContext得到的Environment来检查profile是否处于激活状态。