mybatis插件原理

mybatis的插件原理可參考博文,http://blog.csdn.net/hupanfeng/article/details/9247379,本文可作爲補充。

1mybatis的自定義插件,需要實現Interceptor接口,裏面有三個接口:

Object intercept(Invocation var1) throws Throwable;
Object plugin(Object var1);
void setProperties(Properties var1);

調用順序分別是:setProperties(xxx) => plugin(xx), => intercept(xxx);第一個是設置參數,第二個是生成動態代理(爲考慮性能,一般會判斷是否當前信息是否是當前插件需要攔截的動作),第三個是執行(額,也就是自定義插件的具體內容需要寫在這裏)。


2InterceptorChain裏保存了所有的攔截器,他有一個pluginAll方法用來創建已註冊的插件的動態代理,


該方法的其中一條調用路徑(執行一條SQL時,即使是執行一條SQL這樣簡單的任務,pluginAll也可能會被調用很多次)如下圖所示:


InterceptorChain裏註冊的插件interceptors是在解析XML配置時注入的,



3Object plugin(Object var1);

假設原始對象的類型是T,被攔截的方法是m.

該方法返回插件的代理對象(是JVM臨時生成的一個繼承T的類(如,$Proxy35),同時傳入一個InvocationHandler對象(ProxyWrapper)或者原始對象,該類有三個成員,targetinterceptorsignatureMap

target是下一層插件的代理對象或原始對象(你看,這就構成了代理鏈);

interceptor是當前層次的插件;

signatureMap保存了哪些類(原始對象對應的類)的哪些方法被攔截


4Object intercept(Invocation var1)

參數傳入的是代理鏈接上的下一個插件的相關參數,Invocation同樣包含三個成員,targetmethodargs

target是下一級插件的代理對象或原始對象,method被攔截的方法,args對應參數。

末尾有一句


如果target是插件的話,觸發插件的執行(即經歷代理對象的invoke(xx)=> ProxyWrapperinvoke(xxx)=>插件的intercept(xxx)),如此循環;

如果target是目標類的話,那麼調用被攔截的方法。


5、最外一層的代理對象的invoke方法何時被調用呢?

最外層的代理對象,因爲繼承了T,所以可以顯式調用方法m,從而轉到代理對象的invoke方法,進而轉到ProxyWrapperinvoke方法裏.

例如:


handler是個代理對象時,handler.preparexxx)的調用會轉成代理對象(如類名爲”$Proxy35”的對象)的invoke方法的調用,再轉到ProxyWrapperinvoke方法裏,進而轉到插件的intercept(xx)裏面,你看進入4的循環了。


6ProxyWrapperinvoke方法

這裏,如果被調用的方法是被攔截的方法,那麼調用插件的intercept(xxx)方法,並結束;否則呢,調用原始對象的被攔截方法。






發佈了42 篇原創文章 · 獲贊 19 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章