深入理解 Mybatis 插件開發

2021-02-19 Java後端

關於Mybatis插件,大部分人都知道,也都使用過,但很多時候,我們僅僅是停留在表面上,知道Mybatis插件可以在DAO層進行攔截,如列印執行的SQL語句日誌,做一些權限控制,分頁等功能;但對其內部實現機制,涉及的軟體設計模式,編程思想往往沒有深入的理解。

本篇案例將幫助讀者對Mybatis插件的使用場景,實現機制,以及其中涉及的編程思想進行一個小結,希望對以後的編程開發工作有所幫助。

註:本案例以mybatis 3.4.7-SNAPSHOT版本為例。

PS:文章是挺久之前寫的,當時花了一些心思,存到電腦的word裡,今天正好看到,就是裡面的源碼都是圖片,哈哈哈,湊合著看吧。更多 MyBatis乾貨,可以關注微信公眾號 Java後端 回復 666 下載。

分頁功能

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

公共欄位統一賦值

一般業務系統都會有創建者,創建時間,修改者,修改時間四個欄位,對於這四個欄位的賦值,實際上可以在DAO層統一攔截處理,可以用mybatis插件攔截Executor類的update方法,對相關參數進行統一賦值即可;

性能監控

對於SQL語句執行的性能監控,可以通過攔截Executor類的update, query等方法,用日誌記錄每個方法執行的時間;

其它

其實mybatis擴展性還是很強的,基於插件機制,基本上可以控制SQL執行的各個階段,如執行階段,參數處理階段,語法構建階段,結果集處理階段,具體可以根據項目業務來實現對應業務邏輯。

什麼是Mybatis插件

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

支持攔截的方法執行器Executor(update、query、commit、rollback等方法);參數處理器ParameterHandler(getParameterObject、setParameters方法);結果集處理器ResultSetHandler(handleResultSets、handleOutputParameters等方法);SQL語法構建器StatementHandler(prepare、parameterize、batch、update、query等方法);攔截階段那麼這些類上的方法都是在什麼階段被攔截的呢?為理解這個問題,我們先看段簡單的代碼(摘自mybatis源碼中的單元測試SqlSessionTest類),來了解下典型的mybatis執行流程,如下代碼所示:

通過SqlSessionFactoryBuilder創建SqlSessionFactory對象通過SqlSessionFactory獲取SqlSession對象執行SqlSession對象的selectList方法,查詢結果如下是時序圖,在整個時序圖中,涉及到mybatis插件部分已標紅,基本上就是體現在上文中提到的四個類上,對這些類上的方法進行攔截。

插件配置信息的加載先來看下mybatis是如何加載插件配置的,對應的xml配置信息如下:

根據解析到的類信息創建Interceptor對象;添加到Configuration的interceptorChain攔截器鏈中;

代理對象的生成Mybatis插件的實現機制主要是基於動態代理實現的,其中最為關鍵的就是代理對象的生成,所以有必要來了解下這些代理對象是如何生成的。

觀察源碼,發現這些可攔截的類對應的對象生成都是通過InterceptorChain的pluginAll方法來創建的,進一步觀察pluginAll方法,如下:

遍歷所有攔截器,調用攔截器的plugin方法生成代理對象,注意生成代理對象重新賦值給target,所以如果有多個攔截器的話,生成的代理對象會被另一個代理對象代理,從而形成一個代理鏈條,執行的時候,依次執行所有攔截器的攔截邏輯代碼;接下來看一下我們在編寫攔截器的時候,一個典型的plugin方法實現方式,如下:

典型的動態代理實現,調用的是Proxy.newProxyInstance方法來生成代理對象。

以上邏輯對應的時序圖如下,這裡我們假設聲明了兩個攔截器,那麼在創建target代理對象的時候,最終返回的代理對象proxy2,實際上代理了proxy1,而proxy1又代理了target,:

 攔截邏輯的執行由於真正去執行Executor、ParameterHandler、ResultSetHandler和StatementHandler類中的方法的對象是代理對象(建議將代理對象轉為class文件,反編譯查看其結構,幫助理解),所以在執行方法時,首先調用的是Plugin類(實現了InvocationHandler接口)的invoke方法,如下:首先根據執行方法所屬類獲取攔截器中聲明需要攔截的方法集合;判斷當前方法需不需要執行攔截邏輯,需要的話,執行攔截邏輯方法(即Interceptor接口的intercept方法實現),不需要則直接執行原方法。

可以關注下Interceptor接口的intercept方法實現,一般需要用戶自定義實現邏輯,其中有一個重要參數,即Invocation類,通過改參數我們可以獲取執行對象,執行方法,以及執行方法上的參數,從而進行各種業務邏輯實現,一般在該方法的最後一句代碼都是invocation.proceed()(內部執行method.invoke方法),否則將無法執行下一個攔截器的intercept方法。以上邏輯對應的時序圖如下,這裡我們以執行executor對象的query方法為例,且假設有兩個攔截器存在:

這裡以分頁插件為例,來了解下一般mybatis插件的編寫規則,如下所示:intercept:在此實現自己的攔截邏輯,可從Invocation參數中拿到執行方法的對象,方法,方法參數,從而實現各種業務邏輯, 如下代碼所示,從invocation中獲取的statementHandler對象即為被代理對象,基於該對象,我們獲取到了執行的原始SQL語句,以及prepare方法上的分頁參數,並更改SQL語句為新的分頁語句,最後調用invocation.proceed()返回結果。

簡單的說,mybatis插件就是對ParameterHandler、ResultSetHandler、StatementHandler、Executor這四個接口上的方法進行攔截,利用JDK動態代理機制,為這些接口的實現類創建代理對象,在執行方法時,先去執行代理對象的方法,從而執行自己編寫的攔截邏輯,所以真正要用好mybatis插件,主要還是要熟悉這四個接口的方法以及這些方法上的參數的含義;另外,如果配置了多個攔截器的話,會出現層層代理的情況,即代理對象代理了另外一個代理對象,形成一個代理鏈條,執行的時候,也是層層執行;關於mybatis插件涉及到的設計模式和軟體思想如下:軟體思想:AOP編程思想,降低模塊間的耦合度,使業務模塊更加獨立;不要定義過多的插件,代理嵌套過多,執行方法的時候,比較耗性能;攔截器實現類的intercept方法裡最後不要忘了執行invocation.proceed()方法,否則多個攔截器情況下,執行鏈條會斷掉;連結:www.cnblogs.com/chenpi/p/10498921.html

相關焦點

  • 徹底搞懂MyBatis插件原理及PageHelper原理
    package com.lonelyWolf.mybatis.plugin;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import
  • 建議收藏,mybatis插件原理詳解
    上次發文說到了如何集成分頁插件MyBatis插件原理分析,看完感覺自己better了,今天我們接著來聊mybatis插件的原理。插件原理分析mybatis插件涉及到的幾個類:我將以 Executor 為例,分析 MyBatis 是如何為 Executor 實例植入插件的。Executor 實例是在開啟 SqlSession 是被創建的,因此,我們從源頭進行分析。
  • MyBatis-Plus為啥這麼牛?
    Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用內置分頁插件:基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好插件之後,寫分頁等同於普通 List 查詢分頁插件支持多種資料庫:支持 MySQL、MariaDB
  • Mybatis-Generator,讓你的懶體現到極致!
    一 mybatis-generator介紹在我們對用mybatis對資料庫進行操作的時候,需要編寫實體類、接口和接口映射文件等...雖然這些是一些比較簡單的工作,但是如果操作的表一旦多起來也是比較煩心的一件事,而且是一些無腦工作。現在,有一款mybatis-generation插件可以幫我們自動完成這些事情,只需要簡單的配置既可。
  • 推薦10款效率可以翻倍的IDEA插件,擼碼利器
    筆者閒來無事學了下Idea的操作,在找插件的過程中發現了一些寶藏插件,對我們日常開發或者提升代碼功力都挺有幫助的吧,特此選出十個來推薦給大家~10. FindBugs雖說Idea本身提供的代碼檢查工具已經很強大了,但Idea提供的更多是規範性的檢查,如果需要深入地檢查異常,可以使用此插件。
  • Java程式設計師必須知道的MyBatis經典面試題
    mybatis把sql語句從Java代碼抽離出來,單獨放在XML文件管理,管理非常方便mybatis底層封裝了JDBC接口,並自動將結果映射到Java bean中,大大減少代碼的編寫數量,減少重複的工作量mybatis可以手動編寫SQL語句,靈活控制SQL語句,編寫更好的
  • Mybatis初始化過程簡單總結
    前面連續多篇文章都是在數據mybatis的初始化過程,目前基本完成,是時候做一個總結了。上圖中只畫出了SqlSessionFactory初始化過程以及mapper的加載過程,由於其他比如Configuration的屬性、別名、插件、數據源配置、類型映射處理器的初始化過程比較簡單並沒有囊括進去。
  • Mybatis 分頁插件 3.7.2 發布 - OSCHINA - 中文開源技術交流社區
    Mybatis分頁插件 - PageHelper 如果你也在用Mybatis,建議嘗試該分頁插件,這一定是
  • 匯總一下Intellij IDEA炫酷的插件
    3、彩色括號 Rainbow Brackets4、mybatis插件集合 :MyBatis Log Plugin MyBatisCodeHelperPro Free Mybatis plugin推薦指數:☆☆☆☆☆
  • Mybatis_day01
    ,必須命名XXXMapper.xml這樣的樣式測試開發:使用普通模式進行開發、定義user.xmlHibernate由於是面向對象開發,不能開發比較複雜的業務。應用場景:適合需求變化較少的項目,比如ERP,CRM等等Mybatis框架對jdbc框架進行封裝,屏蔽了jdbc的缺點,開發簡單。Mybatis只需要程式設計師關注sql本身,不需要過多的關注業務。
  • Mybatis-Plus 2.0.2 發布,mybatis crud 插件
    啟動加載 XML 配置時注入單表 SQL 操作 ,為簡化開發工作、提高生產率而生。Mybatis-Plus 啟動注入非攔截實現、性能更優。Documentation1、修復全局配置不起作用 2.0.1 邏輯2、去除byId強制配置類型3、Wrapper Page 等程序優化4、優化AR模式自動關閉資料庫連接(之前需要手動設置事務)5、優化代碼生成器,下劃線名稱註解不處理駝峰,支持自定義更多的模板例如 jsp html 等6、新增 service 層測試7、sql日誌記錄整合至性能分析插件
  • Java程式設計師開發必備 MyBatis高級應用之逆向工程自動生成SQL語句
    MyBatis的一個主要的特點就是需要程式設計師自己編寫sql,那麼如果表太多的話,難免會很麻煩,所以mybatis官方提供了一個逆向工程,可以針對單表自動生成mybatis執行所需要的代碼,一般在開發中,常用的逆向工程方式是通過資料庫的表生成代碼。
  • mybatis-plus 3.0-alpha 發布,代號:超級棒棒糖
    mybatis-plus 3.0-alpha 發布,代號:超級棒棒糖Mybatis-Plus 是一款 Mybatis
  • 寫了10年的代碼,我最怕寫Mybatis這些配置,現在有詳解了
    DOCTYPE generatorConfiguration PUBLIC        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"        "http://mybatis.org/dtd/mybatis-generator-config
  • Java 開發的 10 大必備 Eclipse 插件
    毫無疑問,Eclipse 是 Java 開發最流行的 IDE 之一,而這一切主要歸功於 Eclipse 的插件。據悉,Eclipse 有數百個插件,可用於不同類型的任務,並與其他工具集成,比如從 GitHub、SVN、CVS 等下載代碼的插件。通過使用正確的插件,開發者可以提高開發效率。
  • Mybatis 強大的結果映射器ResultMap
    日常的業務開發通常都會和它打交道,今天就對 resultMap 進行一個詳細講解。文末有 DEMO2. resultMap接下來我們來看看 resultMap 是如何進行映射的。<mapper namespace="cn.felord.mybatis.mapper.EmployeeMapper">    <resultMap id="EmployeeConstructorMap" type="cn.felord.mybatis.entity.Employee">
  • 10道MyBatis面試題,你值得看看
    在我們開發系統時,一般都有性能問題。性能問題主要產生在算法不正確和與資料庫不正確的使用上。可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。7.分頁插件的基本原理是什麼?
  • 五大框架之MyBatis面試經常被問到的問題
    前面講了springmvc和hibernate的一些原理和使用,有些朋友私信我問能不能講一下面試中經常遇到的問題,那麼今天就不講mybatis在項目中怎麼使用的,著重談一下我經常遇到的一些問題吧,無論是筆試題還是面試官問到的一些問題,能想起來的都列舉了下來。
  • Mybatis 通用 Mapper 3.5.0 發布
    通用 Mapper 可以極大的方便開發人員。可以隨意的按照自己的需要選擇通用方法,還可以很方便的開發自己的通用方法。通用 Mapper 更新日誌兼容 mbg 1.3.6 版本。EntityColumn 記錄 EntityField 信息,方便後續擴展使用。