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

    技术2022-07-12  77

    例子:

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

    Processed: 0.017, SQL: 9