springboot 注解说明(@ConditionalOnProperty)

2022-08-09,


springboot 注解说明(@ConditionalOnProperty)

 

应用:根据配置文件的属性决定是否将类注册为bean

 

 

**********************

相关类与注解

 

@ConditionalOnProperty:标注在类或者方法上

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnPropertyCondition.class})
public @interface ConditionalOnProperty {
    String[] value() default {};

    String prefix() default "";

    String[] name() default {};

    String havingValue() default "";

    boolean matchIfMissing() default false;
}

说明:value与name等效,同时配置时,优先使用value;

匹配的key:prefix+"."+name,

若含有key,且设置了havingValue,key对应的value=havingvalue,则匹配,若value与havingValue不等,则不匹配

若含有key,且没有设置havingValue,key对应的value不为false,则匹配,若value为false,则不匹配

如不包含key,且设置了matchingIfMissing=true,则匹配,若matchingIfMissing=false,则不匹配

 

 

@Conditional

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();  //继承condition的类数组
}

 

Condition

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

 

 

OnPropertyCondition

@Order(-2147483608)
class OnPropertyCondition extends SpringBootCondition {
    OnPropertyCondition() {
    }

    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
                                           //获取匹配结果
        List<AnnotationAttributes> allAnnotationAttributes = this.annotationAttributesFromMultiValueMap(metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
        List<ConditionMessage> noMatch = new ArrayList();
        List<ConditionMessage> match = new ArrayList();
        Iterator var6 = allAnnotationAttributes.iterator();

        while(var6.hasNext()) {
            AnnotationAttributes annotationAttributes = (AnnotationAttributes)var6.next();
            ConditionOutcome outcome = this.determineOutcome(annotationAttributes, context.getEnvironment());
            (outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
        }

        if (!noMatch.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
        } else {
            return ConditionOutcome.match(ConditionMessage.of(match));
        }
    }

    private List<AnnotationAttributes> annotationAttributesFromMultiValueMap(MultiValueMap<String, Object> multiValueMap) {
                                      //将属性转换为List<AnnotationAttributes>
        List<Map<String, Object>> maps = new ArrayList();
        multiValueMap.forEach((key, value) -> {
            for(int i = 0; i < value.size(); ++i) {
                Object map;
                if (i < maps.size()) {
                    map = (Map)maps.get(i);
                } else {
                    map = new HashMap();
                    maps.add(map);
                }

                ((Map)map).put(key, value.get(i));
            }

        });
        List<AnnotationAttributes> annotationAttributes = new ArrayList(maps.size());
        Iterator var4 = maps.iterator();

        while(var4.hasNext()) {
            Map<String, Object> map = (Map)var4.next();
            annotationAttributes.add(AnnotationAttributes.fromMap(map));
        }

        return annotationAttributes;
    }

    private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes, PropertyResolver resolver) {
        OnPropertyCondition.Spec spec = new OnPropertyCondition.Spec(annotationAttributes);
        List<String> missingProperties = new ArrayList();
        List<String> nonMatchingProperties = new ArrayList();
        spec.collectProperties(resolver, missingProperties, nonMatchingProperties);
        if (!missingProperties.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, new Object[]{spec}).didNotFind("property", "properties").items(Style.QUOTE, missingProperties));
        } else {
            return !nonMatchingProperties.isEmpty() ? ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, new Object[]{spec}).found("different value in property", "different value in properties").items(Style.QUOTE, nonMatchingProperties)) : ConditionOutcome.match(ConditionMessage.forCondition(ConditionalOnProperty.class, new Object[]{spec}).because("matched"));
        }
    }

    private static class Spec {
        private final String prefix;
        private final String havingValue;
        private final String[] names;
        private final boolean matchIfMissing;

        Spec(AnnotationAttributes annotationAttributes) {
            String prefix = annotationAttributes.getString("prefix").trim();
            if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) {
                prefix = prefix + ".";
            }

            this.prefix = prefix;
            this.havingValue = annotationAttributes.getString("havingValue");
            this.names = this.getNames(annotationAttributes);
            this.matchIfMissing = annotationAttributes.getBoolean("matchIfMissing");
        }

        private String[] getNames(Map<String, Object> annotationAttributes) {
            String[] value = (String[])((String[])annotationAttributes.get("value"));
            String[] name = (String[])((String[])annotationAttributes.get("name"));
            Assert.state(value.length > 0 || name.length > 0, "The name or value attribute of @ConditionalOnProperty must be specified");
            Assert.state(value.length == 0 || name.length == 0, "The name and value attributes of @ConditionalOnProperty are exclusive");
            return value.length > 0 ? value : name;
        }  //name与value如果同时配置,优先使用value

        private void collectProperties(PropertyResolver resolver, List<String> missing, List<String> nonMatching) {
            String[] var4 = this.names;
            int var5 = var4.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String name = var4[var6];
                String key = this.prefix + name;       //key:prefix+"."+name
                if (resolver.containsProperty(key)) {  
                    if (!this.isMatch(resolver.getProperty(key), this.havingValue)) {
                        nonMatching.add(name);
                    }  //如果含有key,且key对应的值不与havingValue匹配,将name添加进nonMatching中
                } else if (!this.matchIfMissing) {
                    missing.add(name);
                }      //如果不包含key,则matchingIfMissing=true,不添加进missing中,为false是添加进missing中
            }

        }

        private boolean isMatch(String value, String requiredValue) {
            if (StringUtils.hasLength(requiredValue)) {
                return requiredValue.equalsIgnoreCase(value); //如果设置了havingValue,value与havingValue相等则匹配,否则不匹配
            } else {
                return !"false".equalsIgnoreCase(value);
            }  //如果没有设置havingValue,value只要不为false则匹配,value为false则不匹配
        }

        public String toString() {
            StringBuilder result = new StringBuilder();
            result.append("(");
            result.append(this.prefix);
            if (this.names.length == 1) {
                result.append(this.names[0]);
            } else {
                result.append("[");
                result.append(StringUtils.arrayToCommaDelimitedString(this.names));
                result.append("]");
            }

            if (StringUtils.hasLength(this.havingValue)) {
                result.append("=").append(this.havingValue);
            }

            result.append(")");
            return result.toString();
        }
    }
}

 

 

**********************

示例

 

*******************

配置文件

 

application.yml

person:
  enabled: true
  name: 瓜田李下
  age: 20

student:
  name: 瓜田李下2
  age: 20

 

*******************

pojo 层

 

Person

@Data
@Component
@ConditionalOnProperty(prefix = "person",value = {"enabled"},havingValue = "true")
@ConfigurationProperties("person")
public class Person {

    private String name;
    private Integer age;
}

 

Student

@Data
@Component
@ConfigurationProperties(prefix = "student")
@ConditionalOnProperty(prefix = "student",value = "enabled",matchIfMissing = true)
public class Student {

    private String name;
    private Integer age;
}

 

*******************

controller 层

 

HelloController

@RestController
public class HelloController {

    @Resource
    private Person person;

    @Resource
    private Student student;

    @RequestMapping("/hello")
    public String hello(){
        System.out.println(person);
        System.out.println(student);

        return "success";
    }
}

 

 

**********************

使用测试

 

localhost:8080/hello

2020-07-06 18:27:20.222  INFO 19064 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-07-06 18:27:20.228  INFO 19064 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 6 ms
Person(name=瓜田李下, age=20)
Student(name=瓜田李下2, age=20)

 

 

本文地址:https://blog.csdn.net/weixin_43931625/article/details/107140919

《springboot 注解说明(@ConditionalOnProperty).doc》

下载本文的Word格式文档,以方便收藏与打印。