package org.springframework.boot.autoconfigure.condition;
...
@Order(Ordered.HIGHEST_PRECEDENCE + 40)
class OnPropertyCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
// Get the parameter value of the ConditionalOnProperty annotation on the original data
List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
List<ConditionMessage> noMatch = new ArrayList<>();
List<ConditionMessage> match = new ArrayList<>();
for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
// Through the attribute value, we can determine whether the information in the configuration information satisfies one by one. () All configuration information can be obtained
ConditionOutcome outcome = determineOutcome(annotationAttributes, context.getEnvironment());
(outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
}
if (!noMatch.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
}
return ConditionOutcome.match(ConditionMessage.of(match));
}
private List<AnnotationAttributes> annotationAttributesFromMultiValueMap(
MultiValueMap<String, Object> multiValueMap) {
...
return annotationAttributes;
}
private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes, PropertyResolver resolver) {
Spec spec = new Spec(annotationAttributes);
List<String> missingProperties = new ArrayList<>();
List<String> nonMatchingProperties = new ArrayList<>();
// Through the attribute value, determine whether the information in the configuration information satisfies
spec.collectProperties(resolver, missingProperties, nonMatchingProperties);
if (!missingProperties.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
.didNotFind("property", "properties").items(Style.QUOTE, missingProperties));
}
if (!nonMatchingProperties.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
.found("different value in property", "different value in properties")
.items(Style.QUOTE, nonMatchingProperties));
}
return ConditionOutcome
.match(ConditionMessage.forCondition(ConditionalOnProperty.class, 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) {
...
}
private String[] getNames(Map<String, Object> annotationAttributes) {
...
}
private void collectProperties(PropertyResolver resolver, List<String> missing, List<String> nonMatching) {
for (String name : this.names) {
String key = this.prefix + name;
if (resolver.containsProperty(key)) {
// havingValue defaults to ""
if (!isMatch(resolver.getProperty(key), this.havingValue)) {
nonMatching.add(name);
}
}
else {
if (!this.matchIfMissing) {
missing.add(name);
}
}
}
}
private boolean isMatch(String value, String requiredValue) {
if (StringUtils.hasLength(requiredValue)) {
return requiredValue.equalsIgnoreCase(value);
}
// HavingValue defaults to "" , so as long as the corresponding attribute is not false and if you do not fill in havingValue in the annotation, the conditon will be matched, that is, it will be loaded
return !"false".equalsIgnoreCase(value);
}
@Override
public String toString() {
...
}
}
}