插件原理

插件簡介

一般情況下,開源框架都會提供插件或其他形式的拓展點,供開發(fā)者自行拓展。這樣的好處是顯而易見的,一是增加了框架的靈活性。二是開發(fā)者可以結(jié)合實際需求,對框架進行拓展,使其能夠更好的工作。以MyBatis為例,我們可基于MyBati s插件機制實現(xiàn)分頁、分表,監(jiān)控等功能。由于插件和業(yè)務(wù) 無關(guān),業(yè)務(wù)也無法感知插件的存在。因此可以無感植入插件,在無形中增強功能

Mybati s作為一個應(yīng)用廣泛的優(yōu)秀的ORM開源框架,這個框架具有強大的靈活性,在四大組件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)處提供了簡單易用的插 件擴展機制。Mybatis對持久層的操作就是借助于四大核心對象。MyBatis支持用插件對四大核心對象進 行攔截,對mybatis來說插件就是攔截器,用來增強核心對象的功能,增強功能本質(zhì)上是借助于底層的 動態(tài)代理實現(xiàn)的,換句話說,MyBatis中的四大對象都是代理對象

l四大攔截對象

允許攔截的方法如下:

執(zhí)行器Executor (update、query、commit、rollback等方法);

SQL語法構(gòu)建器StatementHandler (prepare、parameterize、batch、updates query等方 法);

參數(shù)處理器ParameterHandler (getParameterObject、setParameters方法);

結(jié)果集處理器ResultSetHandler (handleResultSets、handleOutputParameters等方法);

Mybatis插件原理

在四大對象創(chuàng)建的時候

1、每個創(chuàng)建出來的對象不是直接返回的,而是interceptorChain.pluginAll(parameterHandler);

2、獲取到所有的Interceptor (攔截器)(插件需要實現(xiàn)的接口);調(diào)用 interceptor.plugin(target);返回 target 包裝后的對象

3、插件機制,我們可以使用插件為目標(biāo)對象創(chuàng)建一個代理對象;AOP (面向切面)我們的插件可 以

為四大對象創(chuàng)建出代理對象,代理對象就可以攔截到四大對象的每一個執(zhí)行;


自定義插件實現(xiàn)

@Intercepts({

@Signature(type= Executor.class,

? ? ? ? ? ? ? ? ? method ="query",

? ? ? ? ? ? ? ? args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})

})

public class MyPlugin1implements Interceptor {

/*

? ? ? ? 攔截方法:只要被攔截的目標(biāo)對象的目標(biāo)方法被執(zhí)行時,每次都會執(zhí)行intercept方法*/

? ? @Override

? ? public Objectintercept(Invocation invocation)throws Throwable {

System.out.println("對方法進行了增強....");

? ? ? ? //原方法參數(shù)

? ? ? ? Object[] args = invocation.getArgs();

? ? ? ? //原方法

? ? ? ? Method method = invocation.getMethod();

? ? ? ? //目標(biāo)對象

? ? ? ? Object target = invocation.getTarget();

? ? ? ? //這里我們將原來查詢的1 改為3

? ? ? ? Integer u=? (Integer) args[1];

? ? ? ? args[1]=3;

? ? ? ? System.out.println(u);

? ? ? ? return invocation.proceed(); //原方法執(zhí)行

? ? }

/*

? ? ? 主要為了把當(dāng)前的攔截器生成代理存到攔截器鏈中*/

? ? @Override

? ? public Objectplugin(Object target) {

Object wrap = Plugin.wrap(target, this);

? ? ? ? return wrap;

? ? }

/*

? ? ? ? 獲取配置文件的參數(shù)*/

? ? @Override

? ? public void setProperties(Properties properties) {

System.out.println("獲取到的配置文件的參數(shù)是:"+properties);

? ? }

}


配置文件:

配置自定義插件\

測試結(jié)果如下:

測試結(jié)果

源碼分析

Plugin實現(xiàn)了InvocationHandler接口?所以最終執(zhí)行的實際上是invoke方法:

invoke方法

4,在每次創(chuàng)建excutor時候

攔截器執(zhí)行


代理放入攔截器鏈
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容