手寫MyBatis第32彈-設計模式實戰:Builder模式在MyBatis框架中的精妙應用

🥂(?′?`?)您的點贊👍?評論📝?收藏?是作者創作的最大動力🤞

💖📕🎉🔥 支持我:點贊👍+收藏??+留言📝歡迎留言討論

🔥🔥🔥(源碼 + 調試運行 + 問題答疑)

🔥🔥🔥 ?有興趣可以聯系我。

我們常常在當下感到時間慢,覺得未來遙遠,但一旦回頭看,時間已經悄然流逝。對于未來,盡管如此,也應該保持一種從容的態度,相信未來仍有許多可能性等待著我們。?

  1. MyBatis架構基石:SqlSessionFactoryBuilder如何構建整個MyBatis宇宙

  2. 配置文件解析的藝術:深入剖析SqlSessionFactoryBuilder的構建過程

  3. 手寫MyBatis構建者:從XML配置到完整SqlSessionFactory的魔法轉換

  4. 設計模式實戰:Builder模式在MyBatis框架中的精妙應用

  5. MyBatis啟動流程解密:SqlSessionFactoryBuilder如何協調全局配置解析


正文

在MyBatis的架構體系中,有一個看似短暫卻至關重要的組件——SqlSessionFactoryBuilder。它如同一個高效的建筑工程師,負責讀取設計藍圖(配置文件),準備所有建筑材料(配置信息),最終建造出宏偉的SqlSessionFactory大廈。今天,我們將深入探討這個"用完即丟"卻不可或缺的構建者。

一、SqlSessionFactoryBuilder的職責與定位

SqlSessionFactoryBuilder在MyBatis框架中扮演著構建協調者的角色,它的核心使命是將各種分散的配置信息整合成一個完整的、可用的SqlSessionFactory實例。這種設計體現了經典的Builder模式,將復雜對象的構建過程與其表示分離。

為什么需要專門的構建者?

  1. 構建過程復雜:MyBatis的配置涉及多個層面,包括數據源、事務管理器、映射器、類型處理器等,需要專門的組件來協調這些配置的解析和組裝。

  2. 支持多種配置源:需要支持從XML文件、Properties文件、編程式配置等多種方式構建配置。

  3. 構建過程與使用過程分離:避免將復雜的構建邏輯污染到SqlSessionFactory本身,保持類的單一職責。

二、全局配置文件:MyBatis的藍圖

在深入了解構建過程之前,我們先看看MyBatis全局配置文件通常包含哪些內容:

<?xml version="1.0" encoding="UTF-8"?><configuration><!-- 環境配置,支持多環境 --><environments default="development"><environment id="development"><!-- 事務管理器 --><transactionManager type="JDBC"/><!-- 數據源 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="password"/></dataSource></environment></environments><!-- 映射器注冊 --><mappers><mapper resource="mapper/UserMapper.xml"/><mapper class="com.example.mapper.ProductMapper"/><package name="com.example.mapper"/></mappers></configuration>

這些配置項共同構成了MyBatis運行的完整藍圖,SqlSessionFactoryBuilder就是解讀這個藍圖的專家。

三、構建過程詳解:從配置文件到工廠實例

讓我們通過一個序列圖來詳細展示SqlSessionFactoryBuilder的完整構建過程:

現在,讓我們用代碼實現這個構建過程:

第一步:創建SqlSessionFactoryBuilder

public class SqlSessionFactoryBuilder {?public SqlSessionFactory build(InputStream inputStream) {try {// 1. 創建配置解析器XMLConfigBuilder parser = new XMLConfigBuilder(inputStream);// 2. 解析配置,返回完整的Configuration對象Configuration config = parser.parse();// 3. 使用配置創建SqlSessionFactoryreturn new DefaultSqlSessionFactory(config);} catch (Exception e) {throw new RuntimeException("Error building SqlSessionFactory. Cause: " + e);} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {// 忽略關閉異常}}}// 支持其他構建方式public SqlSessionFactory build(Reader reader) {// 類似實現...}public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}}

第二步:實現XMLConfigBuilder(簡化版)

public class XMLConfigBuilder {private final InputStream inputStream;private final Configuration configuration;public XMLConfigBuilder(InputStream inputStream) {this.inputStream = inputStream;this.configuration = new Configuration();}public Configuration parse() {try {// 使用JDK內置的XML解析APIDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(inputStream);Element root = document.getDocumentElement();// 解析environmentsparseEnvironments(root);// 解析mappersparseMappers(root);return configuration;} catch (Exception e) {throw new RuntimeException("Error parsing XML config. Cause: " + e);}}private void parseEnvironments(Element root) {NodeList environmentList = root.getElementsByTagName("environment");if (environmentList.getLength() > 0) {Element envElement = (Element) environmentList.item(0);String id = envElement.getAttribute("id");// 解析數據源Element dataSourceElement = (Element) envElement.getElementsByTagName("dataSource").item(0);DataSource dataSource = createDataSource(dataSourceElement);// 解析事務管理器Element txElement = (Element) envElement.getElementsByTagName("transactionManager").item(0);TransactionFactory txFactory = createTransactionFactory(txElement);// 配置EnvironmentEnvironment environment = new Environment(id, txFactory, dataSource);configuration.setEnvironment(environment);}}private void parseMappers(Element root) {NodeList mapperList = root.getElementsByTagName("mapper");for (int i = 0; i < mapperList.getLength(); i++) {Element mapperElement = (Element) mapperList.item(i);if (mapperElement.hasAttribute("resource")) {// 解析XML映射文件String resource = mapperElement.getAttribute("resource");parseMapperXml(resource);} else if (mapperElement.hasAttribute("class")) {// 解析注解Mapper接口String className = mapperElement.getAttribute("class");parseMapperClass(className);} else if (mapperElement.hasAttribute("package")) {// 解析包下的所有MapperString packageName = mapperElement.getAttribute("package");parseMapperPackage(packageName);}}}private void parseMapperXml(String resource) {try (InputStream mapperStream = Resources.getResourceAsStream(resource)) {XMLMapperParser mapperParser = new XMLMapperParser(mapperStream, configuration);mapperParser.parse();} catch (IOException e) {throw new RuntimeException("Error loading mapper resource: " + resource, e);}}private void parseMapperClass(String className) {try {Class<?> mapperClass = Class.forName(className);configuration.addMapper(mapperClass);} catch (ClassNotFoundException e) {throw new RuntimeException("Error loading mapper class: " + className, e);}}// 其他輔助方法...}
四、SqlSessionFactoryBuilder的生命周期:為何"用完即丟"?

SqlSessionFactoryBuilder的設計遵循了"一次性使用"原則,這基于以下幾個考慮:

  1. 無狀態性SqlSessionFactoryBuilder本身不持有任何狀態信息,它的唯一作用就是構建SqlSessionFactory。一旦構建完成,它的使命就結束了。

  2. 資源釋放:構建過程中可能會占用資源(如文件流),使用后立即銷毀有助于及時釋放這些資源。

  3. 線程安全:由于無狀態,它可以被多線程安全地使用,每個線程都可以創建自己的構建者實例。

  4. 內存優化:避免長時間持有對大型配置對象的引用,減少內存占用。

這種設計模式在很多框架中都有應用,比如Java中的StringBuilder(雖然名稱相似但用途不同)、Spring的BeanDefinitionBuilder等。

五、構建過程中的關鍵技術點
  1. 配置解析的容錯性:良好的錯誤處理和詳細的錯誤信息輸出

  2. 資源管理:確保所有打開的流都能正確關閉

  3. 配置驗證:對必要的配置項進行驗證,避免運行時錯誤

  4. 擴展性考慮:為后續支持更多配置項預留擴展點

六、總結與最佳實踐

通過實現SqlSessionFactoryBuilder,我們完成了MyBatis啟動流程的關鍵一環。這個看似簡單的構建者實際上承擔著重要的協調工作:

  1. 配置整合:將分散的配置信息整合成統一的Configuration對象

  2. 資源協調:協調多個解析器的工作,確保配置的正確加載

  3. 異常處理:提供統一的錯誤處理機制,確保構建過程的穩定性

在實際使用中,我們應該遵循以下最佳實踐:

  • SqlSessionFactoryBuilder作為局部變量使用,避免長期持有

  • 確保配置文件的正確性和完整性

  • 在應用啟動時完成SqlSessionFactory的構建,避免重復構建的開銷

SqlSessionFactoryBuilder雖然生命周期短暫,但它的工作為整個MyBatis框架的正常運行奠定了堅實的基礎。正是這種精妙的職責劃分和設計,使得MyBatis成為一個既靈活又穩定的ORM框架。

下次當你看到SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);這行代碼時,你會知道在這背后發生了一個復雜而精妙的構建過程。這就是框架設計的魅力所在——將復雜性封裝在簡潔的API之后,為開發者提供便捷的使用體驗。


💖學習知識需費心,
📕整理歸納更費神。
🎉源碼免費人人喜,
🔥碼農福利等你領!

💖常來我家多看看,
📕我是程序員扣棣,
🎉感謝支持常陪伴,
🔥點贊關注別忘記!

💖山高路遠坑又深,
📕大軍縱橫任馳奔,
🎉誰敢橫刀立馬行?
🔥唯有點贊+關注成!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96703.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96703.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96703.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小白成長之路-k8s原理(一)

文章目錄前言一、k8s組件1.1master部分1.2node節點二、網絡2.1網絡模型2.2CNI2.3流程2.4網絡解決方案2.5網絡模式三、資源清單3.1概述3.2常見的資源3.3資源清單的編寫四、Pod4.1概念圖4.2pause4.3概述4.4pod生命周期4.5pod探針4.6鉤子4.7pod控制器1.RC 控制器2.RS控制器3.deplo…

木筏求生 PC/手機雙端 單機+聯機(Raft)免安裝中文版

網盤鏈接&#xff1a; 木筏求生 免安裝中文版 名稱&#xff1a;木筏求生 PC/手機雙端 單機聯機&#xff08;Raft&#xff09;免安裝中文版 描述&#xff1a; 無論是獨自一人還是與朋友一起&#xff0c;你的任務是在危險的海洋中度過一場史詩般的海洋冒險 &#xff01;收集…

vue中v-show 和 v-if 指令的區別

v-show 和 v-if 是 Vue.js 中兩個非常重要的指令&#xff0c;都用于條件性地顯示或隱藏元素&#xff0c;但它們的實現方式和適用場景有本質區別。 簡單來說&#xff0c;最核心的區別是&#xff1a; v-if 是 “真正的”條件渲染&#xff0c;它會確保在切換過程中條件塊內的事件監…

Linux中iptables命令

iptables 命令詳解iptables 是 Linux 系統內核級防火墻工具&#xff0c;用于配置、維護和檢查 IPv4 數據包過濾規則&#xff08;IPv6 使用 ip6tables&#xff09;。以下是核心用法&#xff1a;一、基本概念表&#xff08;Tables&#xff09;filter&#xff1a;默認表&#xff0…

【springboot 技術代碼】集成mongodb 詳細步驟

SpringBoot 深度集成 MongoDB 詳細步驟1. MongoDB 簡介與 SpringBoot 集成概述1.1 SpringBoot 集成 MongoDB 的優勢2. 環境準備與依賴配置2.1 版本兼容性矩陣2.2 詳細依賴配置2.3 詳細配置說明2.3.1 單節點配置2.3.2 集群配置3. 實體映射與集合管理3.1 詳細實體類注解3.2 索引管…

云計算-K8s 運維:Python SDK 操作 Job/Deployment/Pod+RBAC 權限配置及自定義 Pod 調度器實戰

簡介 在 Kubernetes 運維中,自動化資源管理與定制化調度是提升效率的核心需求,而 Python SDK 是實現這一目標的關鍵工具。本次圍繞 K8s Python SDK 展開全場景實戰,以 “代碼 + 效果” 雙維度,覆蓋 5 大核心運維場景,Job 自動化創建(先清理重名資源再部署計算任務)、De…

Excel 轉化成JSON

Excel 轉化成JSON import pandas as pd import json import osdef excel_to_json(excel_path, sheet_name0, orientrecords, save_pathNone):"""將Excel文件轉換為JSON格式并可選擇保存到文件參數:excel_path: Excel文件路徑sheet_name: 工作表名稱或索引&#…

Linux 進階用法

一、系統性能調優系統性能調優是 Linux 管理中的關鍵技能&#xff0c;它能顯著提升系統在不同應用場景下的表現。通過針對性的調優&#xff0c;可以解決資源瓶頸問題&#xff0c;提高服務響應速度&#xff0c;優化資源利用率。&#xff08;一&#xff09;CPU 性能調優知識點詳解…

14.蘋果ios逆向-app的調試方式

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

深入理解 React useEffect

一、useEffect基礎概念 1、什么是副作用&#xff08;Side Effects&#xff09;&#xff1f; 在React中&#xff0c;副作用是指那些與組件渲染結果無關的操作&#xff0c;例如&#xff1a; 數據獲取&#xff08;API調用&#xff09;手動修改DOM設置訂閱或定時器記錄日志 2、useE…

Yapi中通過MongoDB修改管理員密碼與新增管理員

如何在Docker部署的Yapi中通過MongoDB修改管理員密碼與新增管理員便捷管理Yapi權限&#xff1a;無需前端重置&#xff0c;直接通過數據庫操作修改密碼及添加管理員一、進入MongoDB容器并連接數據庫 首先&#xff0c;通過以下命令進入運行中的MongoDB容器&#xff1a; docker ex…

【EasyR1】GRPO訓練

官方github&#xff1a;https://github.com/hiyouga/EasyR1 參考&#xff1a;https://opendeep.wiki/hiyouga/EasyR1/quickstart 代碼和環境配置 github&#xff1a;https://github.com/hiyouga/EasyR1 新建一個虛擬環境&#xff1a; python -m venv easyr1 source easyr1/b…

2025年KBS SCI1區TOP,新穎獎勵與ε-貪婪衰減Q-learning算法+局部移動機器人路徑規劃,深度解析+性能實測

目錄1.摘要2.新穎獎勵與ε-貪婪衰減Q-learning算法3.結果展示4.參考文獻5.代碼獲取6.算法輔導應用定制讀者交流1.摘要 路徑規劃是移動機器人的核心任務&#xff0c;需要在高效導航的同時規避障礙。本文提出了一種改進Q-learning算法——定制化獎勵與ε-貪婪衰減Q-learning&…

運行npm run命令報錯“error:0308010C:digital envelope routines::unsupported”

下載的前后端分離架構的開源項目&#xff0c;運行“npm run serve”命令啟動前端服務時報錯“error:0308010C:digital envelope routines::unsupported”&#xff0c;這個錯誤通常是由于Node.js版本與項目依賴不兼容導致的&#xff0c;特別是在Node.js v17版本中&#xff0c;百…

AI計算提效關鍵。自適應彈性加速,基于存算架構做浮點運算

一、自適應彈性加速是提升芯片能效比的有力手段自適應彈性加速技術是現代芯片設計中提升能效比的關鍵路徑之一。它摒棄了傳統芯片在設計時采用的靜態、固化的資源分配與功能設定模式&#xff0c;通過引入動態調整機制&#xff0c;使得芯片能夠根據實時的應用需求和負載變化&…

Spring Boot測試陷阱:失敗測試為何“傳染”其他用例?

一個測試失敗&#xff0c;為何“傳染”其他測試&#xff1f;——Spring Boot 單元測試獨立性與泛型陷阱實戰解析 &#x1f6a9; 問題背景 在日常開發中&#xff0c;我們常會遇到這樣的場景&#xff1a; 正在開發新功能 A&#xff0c;寫了一個 testFeatureA() 測試方法&#xff…

Web開發中的CGI:通用網關接口詳解

一、CGI的設計意圖&#xff1a;解決Web的"靜態"困境 在CGI出現之前&#xff0c;Web服務器只能做一件事&#xff1a;返回預先寫好的靜態文件&#xff08;HTML、圖片等&#xff09;。每個用戶看到的內容都是一模一樣的。 設計意圖很簡單但卻革命性&#xff1a; 讓Web服…

在 SSMS 中查找和打開已保存的查詢文件

在 SSMS 中查找和打開已保存的查詢文件 在 SQL Server Management Studio (SSMS) 中&#xff0c;您可以輕松地查找并打開已保存的查詢文件&#xff08;通常以 .sql 擴展名保存&#xff09;。SSMS 提供了直觀的界面支持直接打開這些文件&#xff0c;無需額外工具。以下是詳細步驟…

Protues使用說明及Protues與Keil聯合仿真實現點亮小燈和流水燈

目錄 1Protues介紹及新建工程 1.1進入軟件 1.2文件創建 1.3默認選項 1.5設計面板 1.6添加元器件 1.7終端模式 1.8激勵源模式 1.9探針模式 1.10儀表 1.11二維直線 1.12字符 2 Protues電路原理圖仿真 2.1 220V交流電轉5V直流電穩壓電路仿真原理圖 2.1.1 仿真原理圖…

Linux PCI 子系統:工作原理與實現機制深度分析

Linux PCI 子系統&#xff1a;工作原理與實現機制深度分析 1. Linux PCI 子系統基礎概念 1.1 PCI/PCIe 基礎概念回顧 總線拓撲&#xff1a; PCI/PCIe 系統是一個樹形結構。CPU 連接到 Root Complex (RC)&#xff0c;RC 連接至 PCIe 交換機 (Switch) 和 PCIe 端點設備 (Endpoint…