<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 框架 Mybatis 插件開發(fā)指南,超詳細(xì)!

          共 4496字,需瀏覽 9分鐘

           ·

          2021-08-15 23:14

          微信搜索逆鋒起筆關(guān)注后回復(fù)編程pdf
          領(lǐng)取編程大佬們所推薦的 23 種編程資料!

          來源:https://www.cnblogs.com/chenpi/p/10498921.html  
          作者:風(fēng)一樣的碼農(nóng)

          背景

          關(guān)于Mybatis插件,大部分人都知道,也都使用過,但很多時候,我們僅僅是停留在表面上,知道Mybatis插件可以在DAO層進(jìn)行攔截,如打印執(zhí)行的SQL語句日志,做一些權(quán)限控制,分頁等功能;但對其內(nèi)部實(shí)現(xiàn)機(jī)制,涉及的軟件設(shè)計(jì)模式,編程思想往往沒有深入的理解。
          本篇案例將幫助讀者對Mybatis插件的使用場景,實(shí)現(xiàn)機(jī)制,以及其中涉及的編程思想進(jìn)行一個小結(jié),希望對以后的編程開發(fā)工作有所幫助。
          注:本案例以mybatis 3.4.7-SNAPSHOT版本為例。
          PS:文章是挺久之前寫的,當(dāng)時花了一些心思,存到電腦的word里,今天正好看到,就是里面的源碼都是圖片,哈哈哈,湊合著看吧。

          Mybatis插件典型適用場景

          分頁功能

          mybatis的分頁默認(rèn)是基于內(nèi)存分頁的(查出所有,再截取),數(shù)據(jù)量大的情況下效率較低,不過使用mybatis插件可以改變該行為,只需要攔截StatementHandler類的prepare方法,改變要執(zhí)行的SQL語句為分頁語句即可;

          公共字段統(tǒng)一賦值

          一般業(yè)務(wù)系統(tǒng)都會有創(chuàng)建者,創(chuàng)建時間,修改者,修改時間四個字段,對于這四個字段的賦值,實(shí)際上可以在DAO層統(tǒng)一攔截處理,可以用mybatis插件攔截Executor類的update方法,對相關(guān)參數(shù)進(jìn)行統(tǒng)一賦值即可;

          性能監(jiān)控

          對于SQL語句執(zhí)行的性能監(jiān)控,可以通過攔截Executor類的update, query等方法,用日志記錄每個方法執(zhí)行的時間;

          其它

          其實(shí)mybatis擴(kuò)展性還是很強(qiáng)的,基于插件機(jī)制,基本上可以控制SQL執(zhí)行的各個階段,如執(zhí)行階段,參數(shù)處理階段,語法構(gòu)建階段,結(jié)果集處理階段,具體可以根據(jù)項(xiàng)目業(yè)務(wù)來實(shí)現(xiàn)對應(yīng)業(yè)務(wù)邏輯。

          Mybatis插件介紹

          什么是Mybatis插件

          與其稱為Mybatis插件,不如叫Mybatis攔截器,更加符合其功能定位,實(shí)際上它就是一個攔截器,應(yīng)用代理模式,在方法級別上進(jìn)行攔截。

          支持?jǐn)r截的方法

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

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

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

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

          攔截階段

          那么這些類上的方法都是在什么階段被攔截的呢?為理解這個問題,我們先看段簡單的代碼(摘自mybatis源碼中的單元測試SqlSessionTest類),來了解下典型的mybatis執(zhí)行流程,如下代碼所示:
          以上代碼主要完成以下功能:
          • 讀取mybatis的xml配置文件信息

          • 通過SqlSessionFactoryBuilder創(chuàng)建SqlSessionFactory對象

          • 通過SqlSessionFactory獲取SqlSession對象

          • 執(zhí)行SqlSession對象的selectList方法,查詢結(jié)果

          • 關(guān)閉SqlSession

          如下是時序圖,在整個時序圖中,涉及到mybatis插件部分已標(biāo)紅,基本上就是體現(xiàn)在上文中提到的四個類上,對這些類上的方法進(jìn)行攔截。

          Mybatis插件實(shí)現(xiàn)機(jī)制

          插件配置信息的加載

          先來看下mybatis是如何加載插件配置的,對應(yīng)的xml配置信息如下:
          對應(yīng)的解析代碼如下,主要做以下工作:
          1. 根據(jù)解析到的類信息創(chuàng)建Interceptor對象;

          2. 調(diào)用setProperties方法設(shè)置屬性變量;

          3. 添加到Configuration的interceptorChain攔截器鏈中;

          以上邏輯對應(yīng)的時序圖如下:

          代理對象的生成

          Mybatis插件的實(shí)現(xiàn)機(jī)制主要是基于動態(tài)代理實(shí)現(xiàn)的,其中最為關(guān)鍵的就是代理對象的生成,所以有必要來了解下這些代理對象是如何生成的。
          Executor代理對象
          ParameterHandler代理對象
          ResultSetHandler代理對象
          StatementHandler代理對象
          觀察源碼,發(fā)現(xiàn)這些可攔截的類對應(yīng)的對象生成都是通過InterceptorChain的pluginAll方法來創(chuàng)建的,進(jìn)一步觀察pluginAll方法,如下:
          遍歷所有攔截器,調(diào)用攔截器的plugin方法生成代理對象,注意生成代理對象重新賦值給target,所以如果有多個攔截器的話,生成的代理對象會被另一個代理對象代理,從而形成一個代理鏈條,執(zhí)行的時候,依次執(zhí)行所有攔截器的攔截邏輯代碼;
          接下來看一下我們在編寫攔截器的時候,一個典型的plugin方法實(shí)現(xiàn)方式,如下:
          再進(jìn)一步查看wrap方法,如下:
          典型的動態(tài)代理實(shí)現(xiàn),調(diào)用的是Proxy.newProxyInstance方法來生成代理對象。
          以上邏輯對應(yīng)的時序圖如下,這里我們假設(shè)聲明了兩個攔截器,那么在創(chuàng)建target代理對象的時候,最終返回的代理對象proxy2,實(shí)際上代理了proxy1,而proxy1又代理了target,:

          攔截邏輯的執(zhí)行

          由于真正去執(zhí)行Executor、ParameterHandler、ResultSetHandler和StatementHandler類中的方法的對象是代理對象(建議將代理對象轉(zhuǎn)為class文件,反編譯查看其結(jié)構(gòu),幫助理解),所以在執(zhí)行方法時,首先調(diào)用的是Plugin類(實(shí)現(xiàn)了InvocationHandler接口)的invoke方法,如下:
          首先根據(jù)執(zhí)行方法所屬類獲取攔截器中聲明需要攔截的方法集合;
          判斷當(dāng)前方法需不需要執(zhí)行攔截邏輯,需要的話,執(zhí)行攔截邏輯方法(即Interceptor接口的intercept方法實(shí)現(xiàn)),不需要則直接執(zhí)行原方法。
          可以關(guān)注下Interceptor接口的intercept方法實(shí)現(xiàn),一般需要用戶自定義實(shí)現(xiàn)邏輯,其中有一個重要參數(shù),即Invocation類,通過改參數(shù)我們可以獲取執(zhí)行對象,執(zhí)行方法,以及執(zhí)行方法上的參數(shù),從而進(jìn)行各種業(yè)務(wù)邏輯實(shí)現(xiàn),一般在該方法的最后一句代碼都是invocation.proceed()(內(nèi)部執(zhí)行method.invoke方法),否則將無法執(zhí)行下一個攔截器的intercept方法。
          以上邏輯對應(yīng)的時序圖如下,這里我們以執(zhí)行executor對象的query方法為例,且假設(shè)有兩個攔截器存在:

          Mybatis插件開發(fā)例子

          這里以分頁插件為例,來了解下一般mybatis插件的編寫規(guī)則,如下所示:
          主要需要實(shí)現(xiàn)三個方法
          1. intercept:在此實(shí)現(xiàn)自己的攔截邏輯,可從Invocation參數(shù)中拿到執(zhí)行方法的對象,方法,方法參數(shù),從而實(shí)現(xiàn)各種業(yè)務(wù)邏輯, 如下代碼所示,從invocation中獲取的statementHandler對象即為被代理對象,基于該對象,我們獲取到了執(zhí)行的原始SQL語句,以及prepare方法上的分頁參數(shù),并更改SQL語句為新的分頁語句,最后調(diào)用invocation.proceed()返回結(jié)果。

          2. plugin:生成代理對象;

          3. setProperties:設(shè)置一些屬性變量;

          小結(jié)

          簡單的說,mybatis插件就是對ParameterHandler、ResultSetHandler、StatementHandler、Executor這四個接口上的方法進(jìn)行攔截,利用JDK動態(tài)代理機(jī)制,為這些接口的實(shí)現(xiàn)類創(chuàng)建代理對象,在執(zhí)行方法時,先去執(zhí)行代理對象的方法,從而執(zhí)行自己編寫的攔截邏輯,所以真正要用好mybatis插件,主要還是要熟悉這四個接口的方法以及這些方法上的參數(shù)的含義;
          另外,如果配置了多個攔截器的話,會出現(xiàn)層層代理的情況,即代理對象代理了另外一個代理對象,形成一個代理鏈條,執(zhí)行的時候,也是層層執(zhí)行;
          關(guān)于mybatis插件涉及到的設(shè)計(jì)模式和軟件思想如下:
          1. 設(shè)計(jì)模式:代理模式、責(zé)任鏈模式;

          2. 軟件思想:AOP編程思想,降低模塊間的耦合度,使業(yè)務(wù)模塊更加獨(dú)立;

          一些注意事項(xiàng):
          1. 不要定義過多的插件,代理嵌套過多,執(zhí)行方法的時候,比較耗性能;

          2. 攔截器實(shí)現(xiàn)類的intercept方法里最后不要忘了執(zhí)行invocation.proceed()方法,否則多個攔截器情況下,執(zhí)行鏈條會斷掉; 

             

          逆鋒起筆是一個專注于程序員圈子的技術(shù)平臺,你可以收獲最新技術(shù)動態(tài)最新內(nèi)測資格BAT等大廠大佬的經(jīng)驗(yàn)增長自身學(xué)習(xí)資料職業(yè)路線賺錢思維,微信搜索逆鋒起筆關(guān)注!

          MyBatis 的執(zhí)行流程,寫得太好了!
          關(guān)于 MyBatis 我總結(jié)了 10 種通用的寫法
          項(xiàng)目實(shí)戰(zhàn) Spring Boot視頻教程 微服務(wù)整合Mybatis


          如有收獲,點(diǎn)個在看,誠摯感謝
          瀏覽 75
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产最新激情视频在线 | 一个人免费看的aaaaaa. | 日本黄在线播放 | 99国精产品在一区二区豆花线 | 97色色色色 |