插件簡介
一般情況下,開源框架都會提供插件或其他形式的拓展點,供開發(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中的四大對象都是代理對象

允許攔截的方法如下:
執(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é)果如下:

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

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

