springboot 注解说明(@ConditionalOnProperty)


springboot 注解说明(@ConditionalOnProperty)

 

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

 

 

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

相关类与注解

 

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

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnPropertyCondition.class})
public @interface ConditionalOnProperty {

    String prefix() default "";     //prefix可不设置

    String[] name() default {};     
    String[] value() default {};    //name、value有且只能设置一个,否则会报错

    String havingValue() default "";
    boolean matchIfMissing() default false;
}

匹配规则:属性文件中查找key(prefix+"."+name)

属性文件中设置了key的值value:

ConditionalOnProperty设置了havingValue:value=havingvalue则匹配若不等则不匹配

ConditionalOnproperty没有设置havingValue:value不等于false则匹配,若为false,则不匹配

属性文件中没有设置key:

ConditionalOnProperty中matchingIfMissing:true匹配,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");
                         //name、value长度都为0,则抛出异常
            Assert.state(value.length == 0 || name.length == 0, "The name and value attributes of @ConditionalOnProperty are exclusive");
                         //name、value长度都大于0,则抛出异常

            return value.length > 0 ? value : name;  //返回长度不为0的value或者name
        }  

        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,
                       //havingValue不为null,key对应的值与havingValue不相等,最终判定不匹配
                       //havingValue为null,属性文件中key对应的值为false,最终判定不匹配
                } else if (!this.matchIfMissing) {
                    missing.add(name);
                }      //如果属性文件中没有key,
                       //属性matchingIfMissing=true,最终判定匹配
                       //属性matchingIfMissing=false,最终判定不匹配
            }

        }

        private boolean isMatch(String value, String requiredValue) {
            if (StringUtils.hasLength(requiredValue)) {
                return requiredValue.equalsIgnoreCase(value); //如果设置了havingValue,value与havingValue相等则匹配,否则不匹配
            } else {
                return !"false".equalsIgnoreCase(value);
            }  //如果没有设置havingValue,属性文件中key对应的value不为false则匹配,为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)

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@ConditionalOnProperty注解是Spring Boot中的一个条件注解,用于根据指定的属性值来决定是否加载或创建一个bean。该注解的作用是根据配置文件中的属性值来动态控制bean的创建过程。 要验证@ConditionalOnProperty注解,您可以按照以下步骤进行操作: 1. 确保您已经添加了Spring Boot的依赖,以便可以使用该注解。 2. 在您的Spring Boot应用程序中选择一个合适的类(通常是配置类或启动类),并在该类上添加@ConditionalOnProperty注解。 3. 在@ConditionalOnProperty注解中,您需要指定一个或多个属性的名称和期望的值。例如,假设您想要根据"myapp.feature.enabled"属性的值来决定是否加载一个bean: ```java @Configuration @ConditionalOnProperty(name = "myapp.feature.enabled", havingValue = "true") public class MyFeatureConfig { // Bean definitions and other configurations } ``` 4. 在配置文件(通常是application.properties或application.yml)中添加相应的属性及其值。例如,在application.properties文件中添加以下内容: ``` myapp.feature.enabled=true ``` 这将启用"MyFeatureConfig"类中的bean加载。 5. 运行您的Spring Boot应用程序,并确保启动过程中没有错误或警告。 如果配置文件中指定的属性值与@ConditionalOnProperty注解中指定的期望值匹配,那么该注解所标注的类或bean将会被加载或创建。如果不匹配,则该类或bean将被跳过。 请注意,@ConditionalOnProperty注解还有其他可用的属性,可以用于更复杂的条件匹配逻辑。您可以参考Spring Boot官方文档以获取更多详细信息和示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值