WPS?2019如何清理云空間?WPS 2019如何將PDF轉換為WORD?
WPS 2019如何清理云空間?進入金山文檔網頁端,點擊我的文檔勾
2023/04/10
@ConditionalOnProperty:根據屬性值來控制類或某個方法是否需要加載。它既可以放在類上也可以放在方法上。
在applicatio.properties或application.yml配置isload_bean = true;
(資料圖片)
#配置是否加載類 is_load_bean: true
編寫加載類,使用@Component進行注解,為了便于區分,我們將@ConditionalOnProperty放在方法上。
/** * @author: jiangjs * @description: 使用@ConditionalOnProperty * @date: 2023/4/24 10:20 **/ @Component @Slf4j public class UseConditionalOnProperty { @Value("${is_load_bean}") private String isLoadBean; @Bean @ConditionalOnProperty(value = "is_load_bean",havingValue = "true",matchIfMissing = true) public void loadBean(){ log.info("是否加載當前類"); } @Bean public void compareLoadBean(){ log.info("加載bean屬性:" + isLoadBean); } }
啟動項目時輸出打印的日志。如圖:
將配置文件的數據信息改成false,則不會打印出結果。
查看@ConditionalOnProperty源碼可以看到該注解定義了幾個屬性。
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { /** * name別名,數組類型,獲取對應property名稱的值,與name不能同時使用 */ String[] value() default {}; /** * 屬性前綴,未指定時,自動以點"."結束,有效前綴由一個或多個詞用點"."連接。 * 如:spring.datasource */ String prefix() default ""; /** * 屬性名稱,配置屬性完整名稱或部分名稱,可與prefix組合使用,不能與value同時使用 */ String[] name() default {}; /** * 可與name組合使用,比較獲取到的屬性值與havingValue的值是否相同,相同才加載配置 */ String havingValue() default ""; /** * 缺少該配置屬性時是否加載,默認為false。如果為true,沒有該配置屬性時也會正常加載;反之則不會生效 */ boolean matchIfMissing() default false; }
查看OnPropertyCondition類中國的getMatchOutcome()方法:
@Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { //獲取所有注解ConditionalOnProperty下的所有屬性match,message ListallAnnotationAttributes = annotationAttributesFromMultiValueMap( metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName())); List noMatch = new ArrayList<>(); List match = new ArrayList<>(); //遍歷注解中的屬性 for (AnnotationAttributes annotationAttributes : allAnnotationAttributes) { //創建判定的結果,ConditionOutcome只有兩個屬性, 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)); }
在上述源碼中determineOutcome()是關鍵方法,我們來看看:
private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes, PropertyResolver resolver) { //初始化 Spec spec = new Spec(annotationAttributes); ListmissingProperties = new ArrayList<>(); List nonMatchingProperties = new ArrayList<>(); //收集屬性,將結果賦值給missingProperties,nonMatchingProperties spec.collectProperties(resolver, missingProperties, nonMatchingProperties); if (!missingProperties.isEmpty()) { //missingProperties屬性不為空,說明設置matchIfMissing的是false,則不加載類 return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec) .didNotFind("property", "properties").items(Style.QUOTE, missingProperties)); } if (!nonMatchingProperties.isEmpty()) { //nonMatchingProperties屬性不為空,則設置的屬性值與havingValue值不匹配,則不加載類 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")); }
Spec是OnPropertyCondition的一個靜態內部類,初始化@ConditionalOnProperty中的屬性。
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 = getNames(annotationAttributes); this.matchIfMissing = annotationAttributes.getBoolean("matchIfMissing"); } //處理name與value private String[] getNames(MapannotationAttributes) { String[] value = (String[]) annotationAttributes.get("value"); String[] name = (String[]) annotationAttributes.get("name"); //限制了value或name必須指定 Assert.state(value.length > 0 || name.length > 0, "The name or value attribute of @ConditionalOnProperty must be specified"); //value和name只能有一個存在,不能同時使用 Assert.state(value.length == 0 || name.length == 0, "The name and value attributes of @ConditionalOnProperty are exclusive"); return (value.length > 0) ? value : name; } private void collectProperties(PropertyResolver resolver, List missing, List nonMatching) { //遍歷names,即value或name的值 for (String name : this.names) { //前綴 + name,獲取配置文件中key String key = this.prefix + name; //驗證配置屬性中包含key if (resolver.containsProperty(key)) { //如包含,則獲取key對應的值,與havingValue的值進行匹配 if (!isMatch(resolver.getProperty(key), this.havingValue)) { //不匹配則添加到nonMatching nonMatching.add(name); } } else { //驗證配置屬性中沒有包含key,判斷是否配置了matchIfMissing屬性 if (!this.matchIfMissing) { //該屬性不為true則添加到missing中 missing.add(name); } } } } private boolean isMatch(String value, String requiredValue) { //驗證requiredValue是否有值 if (StringUtils.hasLength(requiredValue)) { //有值,則進行比較,不區分大小寫 return requiredValue.equalsIgnoreCase(value); } //沒有值,則驗證value是否等于false //這也是為什么name, value不配置值的情況下, 類依然會被加載的原因 return !"false".equalsIgnoreCase(value); } @Override 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(); } }
根據業務需求,我們可以實現配置某些屬性動態地去加載某些類或方法。
到此這篇關于SpringBoot之@ConditionalOnProperty注解使用方法的文章就介紹到這了,更多相關SpringBoot @ConditionalOnProperty注解內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
標簽: