【MyBatis 源码拆解系列】MyBatis 运行原理 - 读取 xml 配置文件

欢迎关注公众号(通过文章导读关注:【11来了】),持续 分享大厂系统设计!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

MyBatis 源码系列文章:
(一)【MyBatis 源码拆解系列】MyBatis 源码如何学习?

MyBatis 运行原理

MyBatis 源码的解析已经有很多了,这里不再重复去写,可以参考开源的 MyBatisDemo,文中示例代码位于 MyBatisDemo - 示例 3

  • 参考源码示例:https://github.com/yeecode/MyBatisDemo

先来介绍一下 MyBatis 运行原理,来对它底层的运行机制有一个整体上的把握,之后再根据各个功能深入去看是如何实现的

MyBatis 初始化使用代码如下:

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {String resource = "mybatis-config.xml";InputStream inputStream = null;try {// 1、读取 xml 配置文件inputStream = Resources.getResourceAsStream(resource);} catch (IOException e) {e.printStackTrace();}// 2、得到 SqlSessionFactorySqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);// 3、创建 SqlSessiontry (SqlSession session = sqlSessionFactory.openSession()) {// 4、通过 SqlSession 获取对应 MapperUserMapper userMapper = session.getMapper(UserMapper.class);User userParam = new User();userParam.setSchoolName("Sunny School");// 5、调用接口展开数据库操作List<User> userList =  userMapper.queryUserBySchoolName(userParam);for (User user : userList) {System.out.println("name : " + user.getName() + " ;  email : " + user.getEmail());}}}
}

在 SpringBoot 中使用 MyBatis,只需要将数据库的配置放在 yml 文件中,再去写好 Mapper 接口和对应的 Mapper.xml 文件就可以使用了,这是因为引入了 mybatis-spring-boot-starter 的 maven 依赖,这些加载工作都通过 SpringBoot 来自动帮我们完成了

而这里只引入了 MyBatis 的 maven 依赖,因此需要自己去读取 MyBatis 的 xml 配置文件,并且进行一些初始化操作,来执行我们在 Mapper.xml 中定义 SQL 语句

接下来会将这 5 个步骤拆分进行介绍

一、MyBatis 读取 xml 配置文件

MyBatis 源码系列文章:

  • (一)MyBatis 源码如何学习?

本节主要介绍流程如下:

image-20240922143233261

先看第一部分 xml 配置文件初始化,要加载 xml 配置,肯定是需要读取 xml 文件并进行解析,再将 xml 文件中的配置项加载到当前对应的对象中,MyBatis 是如何做的呢?

这里为了清晰简洁,只列举部分代码:

// DemoApplication
inputStream = Resources.getResourceAsStream(resource);

先通过 MyBatis 源码 io 包下的 Resources 类将执行的 xml 文件读取为 inputStream

// MyBatis 源码内部 io 包下的 Resource 类
public static InputStream getResourceAsStream(String resource) throws IOException {return getResourceAsStream(null, resource);
}public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);if (in == null) {throw new IOException("Could not find resource " + resource);}return in;
}

适配器模式:

这里涉及了 适配器模式 ,对于 getResourceAsStream(ClassLoader loader, String resource) 方法有两个参数,但是有些调用方只传一个参数,那么就写一个方法对其他未传的参数进行适配 getResourceAsStream(String resource) ,这里就是对 ClassLoader 传入 null 做适配

最终走到 ClassLoaderWrappergetResourceAsStream(resource, loader) 来加载对应的 xml 文件

// MyBatis 源码内部 io 包下的 ClassLoaderWrapper 类
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {return getResourceAsStream(resource, getClassLoaders(classLoader));
}

这里最终读取 xml 文件是通过 ClassLoader 来读取,这里通过 getClassLoaders(classLoader) 方法去获取对应的类加载器

类加载器:

ClassLoader 就是 Java 语言自身的类加载器,作用是 动态加载类(即 .class 文件),同样 xml 文件也可以加载为输入流(InputStream)

不同类型的 ClassLoader 加载资源的位置也是不同的

// MyBatis 源码内部 io 包下的 ClassLoaderWrapper 类
ClassLoader[] getClassLoaders(ClassLoader classLoader) {return new ClassLoader[]{classLoader,defaultClassLoader,Thread.currentThread().getContextClassLoader(),getClass().getClassLoader(),systemClassLoader};
}

如上,该方法返回了 ClassLoader 数组,为什么要返回多个 ClassLoader 呢?

为了确保在多种环境下都可以加载到对应的资源,并且这里返回的 ClassLoader 数组是有一个先后顺序的,从前向后遍历 ClassLoader 数组,只要有一个 ClassLoader 成功加载资源就返回该资源

这里参数传入的 classLoader 在第一个,因此他的优先级最高;systemClassLoader 在最后一个,因此他的优先级最低

扩展:

如果我们也需要实现一个资源加载的优先顺序,也可以参考类似的方式来完成

// MyBatis 源码内部 io 包下的 ClassLoaderWrapper 类
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {for (ClassLoader cl : classLoader) {if (null != cl) {InputStream returnValue = cl.getResourceAsStream(resource);if (null == returnValue) {returnValue = cl.getResourceAsStream("/" + resource);}if (null != returnValue) {return returnValue;}}}return null;
}

如上,获取了 ClassLoader 数组之后,就会遍历类加载器来完成资源的加载,核心代码就是 cl.getResourceAsStream(resource) ,这里会根据 ClassLoader 类型的不同走到具体不同的实现中

这里通过 debug 发现传入的 ClassLoader 数组都是 AppClassLoader,因此进入 AppClassLoader 中可以看到内部如何加载 resource 资源

image-20240921002221817

AppClassLoader 继承自 URLClassLoader,最终走到 URLClassLoader 中,这里具体深层的代码就不细看了,在 getResource() 方法内部,类加载器加载资源涉及到 双亲委派 ,是 JVM 中的内容,也就是找到 parent(父类加载器)去加载对应资源,如果父类加载器都加载不到再自己去加载

public class URLClassLoader extends SecureClassLoader implements Closeable {public InputStream getResourceAsStream(String name) {// Jvm 的双亲委派:会找 parent 也就是父类加载器去完成资源的加载,如果都加载不到,再自己去加载URL url = getResource(name);// ... 省略}
}

总结:

  • 配置文件的读取是通过 JVM 的 类加载器 ClassLoader 来读取的

  • 读取配置文件的方法最终封装在了 ClassLoaderWrapper 类中,该类会返回 ClassLoader[] 数组,以及遍历类加载器去读取文件,并且通过 ClassLoader[] 数组中类加载器的顺序来控制加载的优先级

  • MyBatis 源码中讲 io 相关的操作全部放在了 io 包下,包括 Resources、ClassLoaderWrapper 类都位于 MyBatis 的 io 包下,按照类的功能进行目录之间的划分,这样的好处是需要看哪个功能的代码,去该包下可以快速找到对应的所有类

    包括在 DDD 中,核心也是领域划分,领域之间独立、低耦合,每个领域高度内聚,更方便研发人员梳理和分析对应领域代码

    image-20240921154414640

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1543182.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Nature:科研论文中正确使用ChatGPT的三个原则

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 美国科罗拉多大学安舒茨医学院的生物医学信息学研究员Milton Pividori&#xff0c;一直在探索如何将ChatGPT等AI工具该技术融入课题组日常科研任务&#xff0c;例如进行文献综…

远程升级不成功?背后“凶手”可能是模组差分包…

最近有客户反馈在乡村里频繁出现掉线的情况。通过换货、换SIM卡对比排查测试&#xff0c;发现只有去年某批采购的那批模块在客户环境附近会出现掉线的情况&#xff0c;而今年采购的模块批次就不会掉线&#xff0c;很奇怪。 这个出问题的模块&#xff0c;就是合宙4G-Cat.1低功耗…

01.前端面试题之ts:说说如何在Vue项目中应用TypeScript?

文章目录 一、前言二、使用Componentcomputed、data、methodspropswatchemit 三 、总结 一、前言 与link类似 在VUE项目中应用typescript&#xff0c;我们需要引入一个库vue-property-decorator&#xff0c; 其是基于vue-class-component库而来&#xff0c;这个库vue官方推出…

数据驱动农业——农业中的大数据革命

橙蜂智能公司致力于提供先进的人工智能和物联网解决方案&#xff0c;帮助企业优化运营并实现技术潜能。公司主要服务包括AI数字人、AI翻译、埃域知识库、大模型服务等。其核心价值观为创新、客户至上、质量、合作和可持续发展。 橙蜂智农的智慧农业产品涵盖了多方面的功能&…

静态链接和动态链接的Golang二进制文件

关注TechLead&#xff0c;复旦博士&#xff0c;分享云服务领域全维度开发技术。拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;复旦机器人智能实验室成员&#xff0c;国家级大学生赛事评审专家&#xff0c;发表多篇SCI核心期刊学术论文&#xff0c;阿里云认…

抖音截流神器发布:不限量评论采集,实时推送,提升运营效率

在短视频风靡的今天&#xff0c;抖音成为品牌营销的新战场。如何在海量内容中脱颖而出&#xff0c;提升运营效率成为关键。本文将揭秘一款革命性的抖音运营工具&#xff0c;它不仅支持不限量评论采集&#xff0c;还实现了实时推送功能&#xff0c;助力运营者精准把握用户反馈&a…

保姆级 Stable Diffusion 教程,看完这篇就够了!

在美国科罗拉多州举办了一场新兴数字艺术家竞赛&#xff0c;一幅名为《太空歌剧院》的作品获得“数字艺术/数字修饰照片”类别的一等奖&#xff0c;神奇的是&#xff0c;该作品的作者并没有绘画基础&#xff0c;这幅画是他用 AI 生成的。 这让人们充分见识到AI 在绘画领域惊人的…

Shell实战(一)

Shell实战&#xff08;一&#xff09; 导语程序实例解压缩交互功能描述代码和运行结果实现解析 监视CPU和内存功能描述代码和运行结果实现解析 用户管理功能描述代码和运行结果实现解析 总结 导语 本篇引入三个书上的shell程序设计项目&#xff0c;由于书上的版本较老&#xf…

异构AI算力资源池:智能世界的新型基础设施

随着人工智能技术的飞速发展&#xff0c;AI应用对计算资源的需求日益增长。然而&#xff0c;传统的同构计算资源池无法满足AI应用对计算能力、能耗和成本的多样化需求。为此&#xff0c;异构AI算力资源池应运而生&#xff0c;成为未来智能世界的重要基础设施。 背 景 人工智能…

H3C交换机手动释放DHCP地址

原本的的配置&#xff0c;释放时间10天 导致所有的地址都被使用完 释放了地址池的地址 重新调整了超期时间为8小时

游戏行业数据集成“利器”

《黑神话&#xff1a;悟空》自公布以来&#xff0c;便在游戏界引起了巨大的轰动。这款游戏以其精湛的画面、精彩的剧情和深度的玩法&#xff0c;让无数玩家充满期待。而在其背后&#xff0c;游戏开发者们面临着诸多挑战&#xff0c;其中之一便是数据的集成与管理。竞争激烈的游…

【C++ Primer Plus习题】17.3

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <fstream> using namesp…

LeetCode Hot100 C++ 哈希 49.字母异位词分组

给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排…

2-99 基于matlab多尺度形态学提取眼前节组织

基于matlab多尺度形态学提取眼前节组织&#xff0c;通过应用不同尺度的结构元素进行边缘检测&#xff0c;再通过加权融合的思想来整合检测到的边缘&#xff0c;降低图像噪声的影响&#xff0c;提高边缘检测的精度。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&…

线程的状态及join()插队方法

一、线程的状态 线程整个生命周期中有6种状态&#xff0c;分别为 NEW 新建状态 、RUNNABLE 可运行状态、TERMINATED 终止状态、TIMED_WAITING计时等待状态、WAITING 等待状态、BLOCKED 阻塞状态 线程各个状态之间的转换&#xff1a; 在 JAVA 程序中&#xff0c;一个线程对象通过…

200Kg大载重多旋翼无人机应用前景详解

大载重多旋翼无人机是一类具备高载重能力和长航时特点的无人机系统&#xff0c;它们融合了多旋翼无人机的灵活性与大载重无人机的实用性&#xff0c;广泛应用于多个领域。 1. 航拍与影视制作 在航拍与影视制作领域&#xff0c;200Kg大载重多旋翼无人机凭借其出色的稳定性和载重…

维信诺三年半亏损近85亿:股价今年跌超四成,550亿大手笔投资8.6代

《港湾商业观察》施子夫 在显示面板领域知名度颇高的维信诺&#xff08;002387.SZ&#xff09;还是交出了持续亏损的半年报。从近些年财务数据上看&#xff0c;亏损似乎已经成为了公司甩不掉的包袱。 在盈利能力并不如预期的情况下&#xff0c;维信诺也对外释放要550亿扩产能…

图片切换示例【JavaScript】

在 JavaScript 中实现图片切换可以通过多种方法&#xff0c;下面是一个简单的示例&#xff0c;使用 HTML、CSS 和 JavaScript 来实现图片的切换效果。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta c…

单相电多相电

目录 1. 单相电 2. 多相电 3. 其他多相电系统 单相电和多相电是电力系统中常见的两种供电方式&#xff0c;主要区别在于电力传输的相数。以下分别介绍它们的基本概念、特征、以及应用场景。 1. 单相电 定义&#xff1a; 单相电指的是只有一根火线和一根零线的电力系统。这…

电玩店ps5倒计时软件试用版下载 佳易王电玩计时计费管理系统操作教程

一、前言 电玩店ps5倒计时软件试用版下载 佳易王电玩计时计费管理系统操作教程 佳易王电玩店计时计费软件&#xff0c;有两款&#xff0c;其中一款可显示倒计时剩余分钟数&#xff0c;另外一款是显示用了多长时间&#xff0c;都可以设置定时语音提醒。 二、显示倒计时软件图文…