MyBatis 源碼分析 項目總覽 1.概述 本文主要大致介紹一下MyBatis的項目結構。 引用參考資料《MyBatis技術內幕》 此外,https://mybatis.org/mybatis 3/zh/index.html MyBatis官方也提供了很不錯的中文文檔。對於使用中有碰到一些問題,可 ...
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的整體架構圖
本文由 Janker 創作,採用 CC BY 3.0 CN協議 進行許可。 可自由轉載、引用,但需署名作者且註明文章出處。如轉載至微信公眾號,請在文末添加作者公眾號二維碼。