Spring实战(第四版)读书笔记07——条件化的bean

例子:

@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是否处于激活状态。

猜你喜欢

转载自blog.csdn.net/Nemoosi/article/details/107076776