前言
MyBatis 是一個被廣泛應(yīng)用的持久化框架。一個簡單的使用示例如下所示琴锭,先創(chuàng)建會話工廠莉炉,然后從會話工廠中打開會話撰茎,通過 class 類型和配置生成 Mapper 接口的代理實現(xiàn)泼菌,最后使用 Mapper 進行持久化操作孔庭。
本文將從 MyBatis 中的 SqlSessionFactoryBuilder知举、SqlSessionFactory寇壳、SqlSession 和 Mapper 幾個方面入手簡單分析 MyBatis 的實現(xiàn)原理瓷耙。在后面的系列文章中會進一步具體分析核心類的細節(jié)實現(xiàn)朱躺。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder 使用 Builder 模式去生成 SqlSessionFactory,因此只提供了多個 build 方法搁痛。這些方法可以接受 XML 配置文件的 Reader 或 InputStream 輸入流长搀,也可以傳入 environment 指定環(huán)境或傳入 Properties 作為屬性。
在 build 方法的實現(xiàn)中鸡典,首先根據(jù)傳入的輸入流源请、environment 和 Properties 構(gòu)建 XMLConfigBuilder 對象,然后調(diào)用其 parse() 方法解析 XML 文件得到 Configuration 對象彻况,最后創(chuàng)建 SqlSessionFactory 對象并返回谁尸。
SqlSessionFactory
SqlSessionFactory 是一個工廠接口,默認實現(xiàn)是 DefaultSqlSessionFactory疗垛。SqlSessionFactory 的作用是獲取 SqlSession症汹,因此提供了多個 openSession 方法,支持從 DataSource 數(shù)據(jù)源和一個給定的連接 Connection 中創(chuàng)建 SqlSession贷腕。
openSession 方法的底層實現(xiàn)可以分為 5 步:
①從 Configuration 對象中獲取環(huán)境配置 Environment背镇;
②根據(jù)環(huán)境配置得到事務(wù)工廠 TransactionFactory;
③從事務(wù)工廠得到事務(wù) Transaction泽裳,Transaction 包裝了數(shù)據(jù)庫連接瞒斩,處理數(shù)據(jù)庫連接的創(chuàng)建、準備涮总、提交胸囱、回滾和關(guān)閉;
④創(chuàng)建執(zhí)行器 Executor瀑梗;
⑤創(chuàng)建 SqlSession烹笔,返回 DefaultSqlSession 的實例裳扯。
其中從 DataSource 數(shù)據(jù)源創(chuàng)建 SqlSession 的過程如下所示:
SqlSession
SqlSession 是一個接口,默認實現(xiàn)是 DefaultSqlSession谤职,提供了多種數(shù)據(jù)庫操作方式饰豺,如 select、selectOne允蜈、selectList冤吨、insert、update饶套、delete漩蟆、commit、rollback 和 getMapper 等方法妓蛮。getMapper 方法用于獲取 Mapper 接口的代理實現(xiàn)怠李。在 MyBatis 中建議使用 Mapper 接口操作數(shù)據(jù)庫。
數(shù)據(jù)庫的增刪改查和事務(wù)的提交回滾都是通過 Executor 執(zhí)行的仔引。Executor 有 3 種類型 SIMPLE扔仓、REUSE、BATCH咖耘,默認使用簡易執(zhí)行器 SIMPLE翘簇,REUSE 類型執(zhí)行器重用預處理語句,BATCH 類型執(zhí)行器重用預處理語句和批量更新儿倒。Executor 對象的創(chuàng)建在 Configuration 類型的 newExecutor 方法中進行版保。
Executor 在執(zhí)行過程中,會用到 StatementHandler夫否、ParameterHandler 和 ResultHandler彻犁,其中 StatementHandler 封裝了?java.sql.Statement 的相關(guān)操作,ParameterHandler 封裝了 SQL 對參數(shù)的處理凰慈,ResultHandler 封裝了對返回數(shù)據(jù)集的處理汞幢。Executor 的執(zhí)行過程,就是對這 3 個對象的調(diào)度過程微谓。更多分析在后續(xù)文章中進行森篷。
Mapper
Mapper 是通過 JDK 動態(tài)代理實現(xiàn)的,在 MapperProxyFactory 中創(chuàng)建 MapperProxy 并進行接口代理封裝豺型。對 Mapper 接口的調(diào)用實際上是由 MapperProxy 實現(xiàn)的仲智。
在 MapperProxy 中,實現(xiàn)了 InvocationHandler 的 invoke 方法姻氨。methodCache 是一個 ConcurrentHashMap钓辆,其中存儲了方法與 MapperMethod 的對應(yīng)關(guān)系。從 methodCache 緩存中獲取或創(chuàng)建 MapperMethod 對象,然后調(diào)用 MapperMethod 對象的 execute 方法執(zhí)行數(shù)據(jù)庫操作前联。
創(chuàng)建 MapperMethod 對象時功戚,會在構(gòu)造函數(shù)中初始化 SqlCommand 和MethodSignature。SqlCommand 包含了數(shù)據(jù)庫操作的名稱蛀恩,格式為 “接口名.操作名稱”疫铜,以及 XML 中配置的操作類型茂浮,如 select双谆、update等,把一個 Mapper 接口與 XML中的一個配置結(jié)合起來席揽。MethodSignature 是方法的簽名顽馋,標記了方法的返回值類型,對于使用 RowBounds(offset 和 limit 配置)幌羞、ResultHandler(結(jié)果處理回調(diào))作為參數(shù)的方法記錄參數(shù)位置并初始化參數(shù)處理器寸谜。
在 MapperMethod 的 execute 方法中,根據(jù) SqlCommand 中的配置選擇 SqlSession 的方法属桦,根據(jù) MethodSignature 的配置處理傳入的參數(shù)熊痴,調(diào)用 SqlSession 的方法進行數(shù)據(jù)庫操作,最后根據(jù) MethodSignature 的返回值類型返回操作結(jié)果聂宾。
每周 3 篇學習筆記或技術(shù)總結(jié)果善,面向有一定基礎(chǔ)的 Java 程序員,內(nèi)容涉及 Java 進階系谐、虛擬機巾陕、MySQL、NoSQL纪他、分布式計算鄙煤、開源框架等多個領(lǐng)域。關(guān)注作者或微信公眾號 backend-develop 第一時間獲取最新內(nèi)容茶袒。