欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springboot 注解说明(@ConditionalOnProperty)

程序员文章站 2024-01-25 08:41:52
springboot注解说明(@ConditionalOnProperty)...

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