1. 程式人生 > >Mybatis深入原始碼分析之基於裝飾模式純手寫一級,二級,三級快取

Mybatis深入原始碼分析之基於裝飾模式純手寫一級,二級,三級快取

寫在前面:設計模式源於生活,而又高於生活!

什麼是裝飾者模式

不改變原有物件的基礎上附加功能,相比生成子類更靈活。

裝飾者模式應用場景

Mybatis快取,過濾器,閘道器控制,P2P分控審批

裝飾者模式定義

(1)抽象元件:定義一個抽象介面,來規範準備附加功能的類

(2)具體元件:將要被附加功能的類,實現抽象構件角色介面

(3)抽象裝飾者:持有對具體構件角色的引用並定義與抽象構件角色一致的介面

(4)具體裝飾:實現抽象裝飾者角色,負責對具體構件新增額外功能。

裝飾者程式碼實現

定義一個介面

public interface ComponentCatch {
    /**
     * 定義共同行為的方法標準
     */
    Object getCatch(String key);
    void putCatch(String key,Object value);
}

定義被裝飾角色

/**
 * 【一級快取】,FirstCatch【被裝飾的類】
 */
public class FirstCatch implements ComponentCatch {
    //偽裝成一級快取
    HashMap firstCatchMap=new HashMap();

    public FirstCatch() {
        firstCatchMap.put("1","xuyu");
    }
    public Object getCatch(String key) {
        Object value = firstCatchMap.get(key);
        System.out.println(">>>>>>>呼叫一級快取查詢資料");
        return value;
    }

    public void putCatch(String key, Object value) {
        firstCatchMap.put(key,value);
    }
}

定義抽象裝飾角色

/**
 * 抽象裝飾者:AbstractDecorator,定義【被裝飾者】與【具體裝飾者】共同行為
 */
public abstract class AbstractDecorator implements ComponentCatch {
    protected ComponentCatch baseCatch;

    public AbstractDecorator(ComponentCatch baseCatch) {
        this.baseCatch = baseCatch;
    }
    public Object getCatch(String key) {
        return baseCatch.getCatch(key);
    }
}

定義具體裝飾角色

/**
 * 二級快取:SecondCatch,【裝飾者】
 * SecondCatch:在不改變原有一級快取基礎之上搭建二級快取
 */
public class SecondCatch extends AbstractDecorator {
    //偽裝成二級快取
    HashMap secondCatchMap=new HashMap();

    public SecondCatch(ComponentCatch baseCatch) {
        super(baseCatch);
    }

    public Object getCatch(String key) {
        System.out.println(">>>>>>>呼叫二級快取查詢資料");
        //先查詢二級快取
        Object secondValue = secondCatchMap.get(key);
        //如果二級快取沒有,再查詢一級快取
        if(secondValue==null){
            Object firstValue = super.getCatch(key);
            //如果一級快取有的話
            if(firstValue!=null){
                //將一級快取快取到二級快取
                secondCatchMap.put(key,firstValue);
                secondValue=firstValue;
            }
        }
        return secondValue;
    }
    public void putCatch(String key, Object value) {
    }

}
/**
 * 三級快取【裝飾者】
 * ThiredCatch:在不改變原有二級快取的基礎之上搭建三級快取
 */
public class ThiredCatch extends AbstractDecorator {
    //偽裝成三級快取
    HashMap thiredCatchMap=new HashMap();

    public ThiredCatch(ComponentCatch baseCatch) {
        super(baseCatch);
    }
    public void putCatch(String key, Object value) {
    }
    public Object getCatch(String key) {
        System.out.println(">>>>>>>呼叫三級快取查詢資料");
        //先查詢三級快取
        Object thiredValue = thiredCatchMap.get(key);
        //如果三級快取沒有,再查詢二級快取,如果二級快取為空的話,再查詢一級快取
        if(thiredValue==null){
            Object secondValue = super.getCatch(key);
            //如果二級快取不為空
            if(secondValue!=null){
                //將二級快取快取到三級快取
                thiredCatchMap.put(key,secondValue);
                thiredValue=secondValue;
            }
        }
        return thiredValue;
    }
}

獲取裝飾類

public class FactoryCatch {
    public static ComponentCatch getComponentCatch(){
        ThiredCatch thiredCatch = new ThiredCatch(new SecondCatch(new FirstCatch()));
        return thiredCatch;
    }
    public static void main(String[] args) {
        ComponentCatch getComponentCatch=getComponentCatch();
        Object value1 = getComponentCatch.getCatch("1");
        System.out.println("value1:"+value1);
        System.out.println("###########################");
        Object value2 = getComponentCatch.getCatch("1");
        System.out.println("value2:"+value2);
    }
}

輸出結果

>>>>>>>呼叫三級快取查詢資料
>>>>>>>呼叫二級快取查詢資料
>>>>>>>呼叫一級快取查詢資料
value1:xuyu
###########################
>>>>>>>呼叫三級快取查詢資料
value2:xuyu

Mybatis原始碼分析裝飾者設計模式

原始碼分析圖

部分原始碼

public Cache useNewCache(Class<? extends Cache> typeClass,
      Class<? extends Cache> evictionClass,
      Long flushInterval,
      Integer size,
      boolean readWrite,
      boolean blocking,
      Properties props) {
    typeClass = valueOrDefault(typeClass, PerpetualCache.class);
    evictionClass = valueOrDefault(evictionClass, LruCache.class);
    Cache cache = new CacheBuilder(currentNamespace)
        .implementation(typeClass)
         //新增二級快取
        .addDecorator(evictionClass)
        .clearInterval(flushInterval)
        .size(size)
        .readWrite(readWrite)
        .blocking(blocking)
        .properties(props)
        .build();
    configuration.addCache(cache);
    currentCache = cache;
    return cache;
  }
 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    //獲取二級快取
    Cache cache = ms.getCache();
    //判斷二級快取是否存在
    if (cache != null) {
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
public Object getObject(Object key) {
    requests++;
    //這裡獲取二級快取
    final Object value = delegate.getObject(key);
    if (value != null) {
      hits++;
    }
    if (log.isDebugEnabled()) {
      log.debug("Cache Hit Ratio [" + getId() + "]: " + getHitRatio());
    }
    return value;
  }

總結:

裝飾模式和代理模式區別?

代理模式:在方法之前和之後實現處理,在方法上實現增強,隱藏真實方法的真實性,保證安全。

裝飾模式:不改變原有的功能,實現增強,不斷新增很多裝飾。

版權@須臾之餘https://my.oschina.net/u/3995125

本文參考:螞蟻課堂:http: