Mybatis深入原始碼分析之基於裝飾模式純手寫一級,二級,三級快取
阿新 • • 發佈:2019-06-19
寫在前面:設計模式源於生活,而又高於生活!
什麼是裝飾者模式
在不改變原有物件的基礎上附加功能,相比生成子類更靈活。
裝飾者模式應用場景
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