🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。 

  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…