MyBatis 源碼分析-項目總覽

  • 2020 年 3 月 11 日
  • 筆記

MyBatis 源碼分析-項目總覽

1.概述

本文主要大致介紹一下MyBatis的項目結構。引用參考資料《MyBatis技術內幕》

此外,https://mybatis.org/mybatis-3/zh/index.html MyBatis官方也提供了很不錯的中文文檔。對於使用中有碰到一些問題,可以參考一下。

2.模組劃分

MyBatis在項目模組劃分還是很清晰的。各個模組層次以及具體作用,如下:

模組 層次 定義
session 介面層 提供給外部使用的介面API
scripting 核心處理層 解析映射文件中的動態SQL節點。並形成資料庫可執行的SQL語句。
mapping 核心處理層 映射
builder 核心處理層 配置解析
executor 核心處理層 執行器模組,串聯整個執行流程。
plugin 核心處理層 插件模組:提供插件介面,通過自定義插件方式對MyBatis進行拓展
cursor 核心處理層 游標模組
reflection 基礎支援層 反射模組:mybatis專門對反射模組進行封裝。提供更加簡單易用的API
type 基礎支援層 類型轉換模組:Mybatis為簡化配置提供了別名機制。提供java類型與JDBC類型轉換
logging 基礎支援層 日誌模組:主要是集成第三方日誌
io 基礎支援層 資源載入模組:對類載入器進行了封裝。確定類載入器順序,並提供載入文件,以及其他資源的功能
datasource 基礎支援層 數據源模組:mybatis自身提供響應的數據源實現,也提供與第三方數據集成的介面。
transaction 基礎支援層 事務管理模組:Mybatis 對資料庫的事務進行了抽象
parsing 基礎支援層 解析器模組:提供兩個功能:1. 對XPath進行封裝 2為處理動態sql語句中的佔位符提供支援
cache 基礎支援層 快取模組:提供一級快取、二級快取。優化查詢
binding 基礎支援層 Binding模組:將自定義的介面與映射配置文件關聯起來。通過調用mapper介面完成資料庫執行。
exceptions 基礎支援層 異常處理
annotations 基礎支援層 註解模組
jdbc 其他 JDBC模組
lang 其他 Lang模組

整體結構

整體分為三層:

  • 介面層:定義了MyBatis暴露給應用程式調用的API。
  • 核心處理層:實現了MyBatis的核心處理流程,包括MyBatis初始化以及完成一次資料庫操作的涉及的全部流程。
  • 基礎支援層:為核心處理層提供了良好的基礎支撐。例如:反射、類型轉換、日誌、快取、事務等模組。

3.1 基礎支援層

3.1.1 反射模組

對應reflection

Java中的反射雖然功能強大,但對大多數開發人員來說,寫出高品質的反射程式碼還是有一定難度的。MyBatis 中專門提供了  反射模組,該模組對Java原生的反射進行了良好的封裝,提供了更加簡潔易用的API, 方便上層使調用,並且對反射操作進行  了一系列優化,例如快取了類的元數據,提高了反射操作的性能。

3.1.2 類型轉換模組

對應type

正如前面示例所示,MyBatis 為簡化配置文件提供了別名機制,該機制是類型轉換模組的主要功能之一。 類型轉換模組的  另-一個功能是實現JDBC類型與Java類型之間的轉換,該功能在為SQL語句綁定實參以及映射查詢結果集時都會涉及。在為  SQL語句綁定實參時,會將數據由Java類型轉換成JDBC類型;而在映射結果集時,會將數據由JDBC類型轉換成Java類型。類  型轉換模組的具體原理在第2章詳述。

3.1.3 日誌模組

對應logging

無論在開發測試環境中,還是在線上生產環境中,日誌在整個系統中的地位都是非常重要的。良好的日誌功能可以幫助開發人  員和測試人員快速定位Bug程式碼,也可以幫助運維人員快速定位性能瓶頸等問題。目前的Java世界中存在很多優秀的日誌框  架,例如Log4j、Log4j2、 slf4j 等。MyBatis 作為-一個設計優良的框架,除了提供詳細的日誌輸出資訊,還要能夠集  成多種日誌框架,其日誌模組的一個主要功能就是集成第三方日誌框架。

3.1.4 資源載入模組

對應io

資源載入模組主要是對類載入器進行封裝,確定類載入器的使用順序,並提供了載入類文件以及其他資源文件的功能。

3.1.5 解析器模組

對應parsing

解析器模組的主要提供了兩個功能:一個功能是對XPath進行封裝,為MyBatis初始化時解析mybatis- config.xml配置文  件以及映射配置文件提供支援;另一個功能是為處理動態SQL語句中的佔位符提供支援。

3.1.6 數據源模組

對應datasource

數據源是實際開發中常用的組件之一。 現在開源的數據源都提供了比較豐富的功能,例如,連接池功能、檢測連接狀態等,  選擇性能優秀的數據源組件對於提升ORM框架乃至整個應用的性能都是非常重要的。MyBatis 自身提供了相應的數據源實  現,當然MyBatis也提供了與第三方數據源集成的介面,這些功能都位於數據源模組之中。

3.1.7 事務管理

對應transaction

MyBatis對資料庫中的事務進行了抽象,其自身提供了相應的事務介面和簡單實現。在很多場景中,MyBatis 會與Spring  框架集成,並由Spring框架管理事務

3.1.8 快取模組

對應cache

在優化系統性能時,優化資料庫性能是非常重要的一個環節,而添加快取則是優化資料庫時最有效的手段之一。正確、合理地  使用快取可以將一部分資料庫請求攔截在快取這一層。MyBatis 中提供了一 級快取和二級快取,而這兩級快取都是依賴於基  礎支援層中的快取模組實現的。這裡需要讀者注意的是,MyBatis中自帶的這兩級快取與MyBatis 以及整個應用是運行在同  一個JVM中的,共享同一塊堆記憶體。如果這兩級快取中的數據量較大,則可能影響系統中其他功能的運行,所以當需要快取大  量數據時,優先考慮使用Redis、Memcache 等快取產品。

3.1.9 Binding模組

對應binding

通過前面的示例我們知道,在調用SqlSession相應方法執行資料庫操作時,需要指定映射文件中定義的SQL節點,如果出現  拼寫錯誤,我們只能在運行時才能發現相應的異常。為了儘早發現這種錯誤,MyBatis 通過Binding模組將用戶自定義的  Mapper介面與映射配置文件關聯起來,系統可以通過調用自定義Mapper介面中的方法執行相應的SQL語句完成資料庫操作,  從而避免上述問題。值得讀者注意的是,開發人員無須編寫自定義Mapper介面的實現,MyBatis 會自動為其創建動態代理對  象。在有些場景中,自定義Mapper介面可以完全代替映射配置文件,但有的映射規則和SQL語句的定義還是寫在映射配置文件  中比較方便,例如動態SQL語句的定義。

3.1.10 註解模組

對應annotation

隨著 Java 註解的慢慢流行,MyBatis 提供了註解的方式,使得我們方便的在 Mapper 介面上編寫簡單的資料庫 SQL 操作程式碼,而無需像之前一樣,必須編寫 SQL 在 XML 格式的 Mapper 文件中。雖然說,實際場景下,大家還是喜歡在 XML 格式的 Mapper 文件中編寫響應的 SQL 操作。

3.1.11 異常模組

對應 exceptions

定義了 MyBatis 專有的 PersistenceException 和 TooManyResultsException 異常,此外還包ExceptionFactory異常工廠。

3.2 核心處理層

3.2.1 配置解析

對應executor

在MyBatis初始化過程中,會載入mybatis config.xml配置文件、映射配置文件以及Mapper介面中的註解資訊,解析後  的配置資訊會形成相應的對象並保存到Configuration對象中。例如,示例中定義的<resultMap>節點(即ResultSet的映  射規則)會被解析成ResultMap對象;示例中定義的<result>節點(即屬性映射)會被解析成ResultMapping對象。之後,利  用該Configuration對象創建SqlSessionFactory對象。待MyBatis 初始化之後,開發人員可以通過初始化得到  SqlSessionFactory 創建SqlSession對象並完成資料庫操作。

3.2.2 SQL解析與Scripting模組

對應executor scripting

拼湊SQL語句是一件煩瑣且易出錯的過程,為了將開發人員從這項枯燥無趣的工作中解脫出來,MyBatis實現動態SQL語句的  功能,提供了多種動態SQL語句對應的節點,例如,<where>節點、 <if>節點、 <foreach> 節點等。通過這些節點的組合  使用,開發人員可以寫出幾乎滿足所有需求的動態SQL語句。MyBatis中的scripting模組會根據用戶傳入的實參,解析映射  文件中定義的動態SQL節點,並形成資料庫可執行的SQL語句。之後會處理SQL語句中的佔位符,綁定用戶傳入的實參。

3.2.3 SQL執行

對應executor

SQL語句的執行涉及多個組件,其中比較重要的是Executor 、StatementHandler 、ParameterHandler和  ResultSetHandler. Executor 主要負責維護- - 級快取和二級快取,並提供事務管理的相關操作,它會將資料庫相關  操作委託給StatementHandler完成。StatementHandler首先通過ParameterHandler 完成SQL語句的實參綁定,然後  通過java. sql.Statement對象執行SQL語句並得到結果集,最後通過ResultSetHandler完成結果集的映射,得到結果  對象並返回。

3.2.4 插件

對應plugin

Mybatis 自身的功能雖然強大,但是並不能完美切合所有的應用場景,因此MyBatis提供了插件介面,我們可以通過添加用  戶自定義插件的方式對MyBatis進行擴展。用戶自定義插件也可以改變Mybatis的默認行為,例如,我們可以攔截SQL語句並  對其進行重寫。由於用戶自定義插件會影響MyBatis的核心行為,在使用自定義插件之前,開發人員需要了解MyBatis內部的  原理,這樣才能編寫出安全、高效的插件。

3.3 介面層

對應session

介面層相對簡單,其核心是SqlSession 介面,該介面中定義了MyBatis 暴露給應用程式調用的API,也就是上層應用與  MyBatis交互的橋樑。介面層在接收到調用請求時,會調用核心處理層的相應模組來完成具體的資料庫操作。

3.4 其他層

3.4.1 JDBC模組

對應 jdbc

JDBC單元測試支援類。【只能說是個測試掛件,白送都不要的那種,隨便看看得了 】

3.4.2 Lang模組

裡面只包含兩個註解【從調用上好像沒有任何類用到這個。不知道幹啥用的!!原諒我的無知。】

3.5 小結

整體來說,MyBatis的程式碼結構還是比較簡單易懂的。並且分包也比較清晰,見名知意。下面就是MyBatis的整體架構圖