黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Mybatis插件原理

Mybatis插件原理

更新時間:2021-07-16 15:56:40 來源:動力節(jié)點 瀏覽1194次

當我們使用Mybatis的時候,總會使用到各種插件,如PageHelper(分頁插件)等,當我們需要自定義插件來改變,就必須了解插件的實現(xiàn)原理。

概述

Mybatis插件又稱攔截器,Mybatis采用責(zé)任鏈模式,通過動態(tài)代理組織多個插件(攔截器),通過這些插件可以改變Mybatis的默認行為。MyBatis允許你在已映射語句執(zhí)行過程中的某一點進行攔截調(diào)用。默認情況下,MyBatis允許使用插件來攔截的方法調(diào)用包括:

  • Executor(update,query,flushStatements,commit,rollback,getTransaction,close,isClosed)攔截執(zhí)行器的方法;
  • ParameterHandler(getParameterObject,setParameters)攔截參數(shù)的處理;
  • ResultSetHandler(handleResultSets,handleOutputParameters)攔截結(jié)果集的處理;
  • StatementHandler(prepare,parameterize,batch,update,query)攔截Sql語法構(gòu)建的處理;

Mybatis四大接口

mybatis插件

上圖Mybatis框架的整個執(zhí)行過程。Mybatis插件能夠?qū)t四大對象進行攔截,可以包含到了Mybatis一次會議的所有操作。可見Mybatis的的插件很強大。

  • Executor是Mybatis的內(nèi)部執(zhí)行器,它負責(zé)調(diào)用StatementHandler操作數(shù)據(jù)庫,并把結(jié)果集通過ResultSetHandler進行自動映射,另外,他還處理了二級緩存的操作。從這里可以看出,我們也是可以通過插件來實現(xiàn)自定義的二級緩存的。
  • StatementHandler是Mybatis直接和數(shù)據(jù)庫執(zhí)行sql腳本的對象。另外它也實現(xiàn)了Mybatis的一級緩存。這里,我們可以使用插件來實現(xiàn)對一級緩存的操作(禁用等等)。
  • ParameterHandler是Mybatis實現(xiàn)Sql入?yún)⒃O(shè)置的對象。插件可以改變我們Sql的參數(shù)默認設(shè)置。
  • ResultSetHandler是Mybatis把ResultSet集合映射成POJO的接口對象。我們可以定義插件對Mybatis的結(jié)果集自動映射進行修改。

攔截器為什么能夠攔截(四大接口) 

public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
    parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
    return parameterHandler;
}

public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
    ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
    return resultSetHandler;
}

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
}

public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
        executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
        executor = new ReuseExecutor(this, transaction);
    } else {
        executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
        executor = new CachingExecutor(executor, autoCommit);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
}

這4個方法實例化了對應(yīng)的對象之后,都會調(diào)用interceptorChain的pluginAll方法,那么下面我們在來看pluginAll干了什么

public class InterceptorChain {

    private final List<Interceptor> interceptors = new ArrayList<Interceptor>();

    public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {
            target = interceptor.plugin(target);
        }
        return target;
    }

    public void addInterceptor(Interceptor interceptor) {
        interceptors.add(interceptor);
    }

    public List<Interceptor> getInterceptors() {
        return Collections.unmodifiableList(interceptors);
    }
}

原來這個pluginAll方法就是遍歷所有的攔截器,然后順序執(zhí)行我們插件的plugin方法,一層一層返回我們原對象(Executor/ParameterHandler/ResultSetHander/StatementHandler)的代理對象。當我們調(diào)用四大接口對象的方法時候,實際上是調(diào)用代理對象的響應(yīng)方法,代理對象又會調(diào)用四大接口對象的實例。

攔截器Interceptor

Mybatis的插件實現(xiàn)要實現(xiàn)Interceptor接口,我們看下這個接口定義的方法。

public interface Interceptor {
    Object intercept(Invocation invocation) throws Throwable;
    Object plugin(Object target);
    void setProperties(Properties properties);
}

這個接口只聲明了三個方法。

  • setProperties方法是在Mybatis進行配置插件的時候可以配置自定義相關(guān)屬性,即:接口實現(xiàn)對象的參數(shù)配置
  • plugin方法是插件用于封裝目標對象的,通過該方法我們可以返回目標對象本身,也可以返回一個它的代理,可以決定是否要進行攔截進而決定要返回一個什么樣的目標對象,官方提供了示例:return Plugin.wrap(target,this);
  • intercept方法就是要進行攔截的時候要執(zhí)行的方法

官方推薦插件開發(fā)方式

@Intercepts({@Signature(type = Executor.class, method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class TestInterceptor implements Interceptor {
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget(); //被代理對象
        Method method = invocation.getMethod(); //代理方法
        Object[] args = invocation.getArgs(); //方法參數(shù)
        // do something ...... 方法攔截前執(zhí)行代碼塊
        Object result = invocation.proceed();
        // do something .......方法攔截后執(zhí)行代碼塊
        return result;
    }
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
}

簡單編寫Mybatis插件

注:MyBatis默認沒有一個攔截器接口的實現(xiàn)類,開發(fā)者可以實現(xiàn)符合自己需求的攔截器。

下面的MyBatis官網(wǎng)的一個攔截器實例:

@Intercepts({@Signature(type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
    }
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    public void setProperties(Properties properties) {
    }
}

全局xml配置:

<plugins>
<plugin interceptor="org.format.mybatis.cache.interceptor.ExamplePlugin"></plugin>
</plugins>

這個攔截器攔截Executor接口的update方法(其實也就是SqlSession的新增,刪除,修改操作),所有執(zhí)行executor的update方法都會被該攔截器攔截到。

以上就是動力節(jié)點小編介紹的"Mybatis插件原理",希望對大家有幫助,想了解更多可查看Mybatis視頻教程。動力節(jié)點在線學(xué)習(xí)教程,針對沒有任何Java基礎(chǔ)的讀者學(xué)習(xí),讓你從入門到精通,主要介紹了一些Java基礎(chǔ)的核心知識,讓同學(xué)們更好更方便的學(xué)習(xí)和了解Java編程,感興趣的同學(xué)可以關(guān)注一下。

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 黄网在线免费看 | 香蕉1024 | 日韩美女拍拍免费视频网站 | 天堂va欧美va亚洲va国产 | 成人综合久久综合 | 日韩欧美一区二区三区在线观看 | 精品欧美日韩一区二区 | 免费欧美一级 | 日韩高清伦理片中字在线观看 | a欧美在线| 日本一区二区三区欧美在线观看 | 亚洲αv| 色婷婷久 | 欧美精品一区二区三区在线播放 | 成人超污免费网站在线看 | 亚洲欧美激情精品一区二区 | 国产成人午夜精品影院游乐网 | 欧美巨大xxxx做受孕妇视频 | 黄色香蕉视频 | 人人爱天天做夜夜爽2020麻豆 | 国产高清一区二区三区四区 | 天天摸天天澡天天碰天天弄 | 国产精品1024免费看 | 精品视频一区在线观看 | 亚洲欧美日韩中文字幕在线不卡 | 一本大道香蕉高清视频在线 | 草在线视频 | 欧美一区二区三区在观看 | 国产一级特黄一级毛片 | 成人高清在线观看播放 | 日本福利网址 | 狠狠干狠狠爱 | 成人在线免费视频播放 | 最近韩国日本免费免费版 | 欧美成人乱弄视频 | 久久国产高清一区二区三区 | 在线免费日韩 | 国产全黄三级国产全黄三级书 | free性欧美极度另类性性欧美 | 亚洲欧美一区二区三区国产精品 | 日韩不卡视频在线 |