SpringBoot自定義Condition注解


    最近碰到個這樣的需求,需要同一套代碼適配個版本數據庫(數據庫不同,且部分表的字段及關聯關系可能會不同),即這套代碼配置不同的數據庫都能跑。項目采用的框架為SpringBoot+Mybatis。經過一番思考,思路如下:
    (1)在業務層(service)和數據訪問層(Mapper)之間添加一層適配層,用來屏蔽數據庫的差異
    (2) 適配層中代碼均采用接口加實現類的方式,不同的數據庫用的實現類不同
     (3)業務層(service)中全部采用面向接口編程
     (4)項目啟動后只實例化和數據庫相匹配的適配層實現類
    實現上面的一個關鍵點是對bean的實例化添加一個條件判斷來控制。其實SpringBoot里面新增了很多條件注解,能實現這個功能。但是都有些局限性,最終是采用自定義條件注解的方案。

一、SpringBoot自帶的注解ConditionalOnProperty

          這個注解不做過多的解釋,只說通過這個注解怎么實現我們的功能。
假設我們application.properties中配置一個配置項為
#bean實例化條件配置項
conditionKey=1.0
    那么只需要加上@ConditionalOnProperty的name和havingValue就能實現,只有配置文件中name對應的配置項的值和havingValue內容一致才實例化這個對象。
針對我們上面配置的application.properties的內容,@ConditionalOnProperty的使用案例如下面代碼所示
// 僅當conditionKey==1.0的時候實例化這個類
@Component
@ConditionalOnProperty(name = "conditionKey", havingValue = "1.0")
public class Manage1Impl  implements  MyManage{

    @Override
    public void sayHello() {
        System.out.println("我是實現類01");
    }

    @PostConstruct
    public void init() {
        this.sayHello();
    }
}
    這個注解的局限性 這個注解的havingValue里面只能配置一個值。
    由於項目個性化需求,希望這個havingValue可以配置多個值, name對應的配置項的Value只要滿足havingValue里面多個值的就表示匹配正確。即,havingValue里面可以配置多個值,name對應配置項的值來和havingValue匹配時,采用邏輯或匹配,滿足一個值就算匹配正確。

二、自定義條件注解

(1)思路

          注解里面有2個屬性,具體如下
      • name:String類型,用來接受application.properties的配置項的key
      • havingValue:String數組類型,用來和name對應key的Value進行匹配

(2)定義注解

package com.zxy.config;

import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
/**
 * 自定義條件注解
 * @author ZENG.XIAO.YAN
 * @version 1.0
 * @Date 2019-04-15
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(CustomOnPropertyCondition.class)
public @interface CustomConditionalOnProperty {

    /**
     * 條件變量的name
     */
    String name() default "";

    /**
     * havingValue數組,支持or匹配
     */
    String[] havingValue() default {};

}

(3)定義注解的匹配規則

package com.zxy.config;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;

/**
 * 自定義條件注解的驗證規則
 * @author ZENG.XIAO.YAN
 * @version 1.0
 * @Date 2019-04-15
 */
public class CustomOnPropertyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(CustomConditionalOnProperty.class.getName());
        String propertyName = (String) annotationAttributes.get("name");
        String[] values = (String[]) annotationAttributes.get("havingValue");
        if (0 == values.length) {
            return false;
        }
        String propertyValue = conditionContext.getEnvironment().getProperty(propertyName);
        // 有一個匹配上就ok
        for (String havingValue : values) {
            if (propertyValue.equalsIgnoreCase(havingValue)) {
                return true;
            }
        }
        return false;
    }
}

(4)使用案例

    直接參考下面2圖吧
         

         

三、小結

    自定義Condition注解,主要就2步
(1)定義一個條件注解
(2)定義一個條件的校驗規則


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM