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的整體架構圖