Mybatis源码02 - 初始化基本过程(引导层部分)
初始化基本过程(引导层部分)
文章目录
- 初始化基本过程(引导层部分)
- 一:初始化的方式及引入
- 二:初始化方式-XML配置文件
- 1:MyBatis初始化基本过程
- 2:创建Configuration对象的过程
- 2.1:将XML的信息转换为Document对象
- 2.2:调用parse()方法
- 2.3:设置到Configuration对象中
- 三:初始化方式-基于Java API
MyBatis和数据库的交互有两种方式有Java API和Mapper接口两种,所以MyBatis的初始化必然也有两种;
那么MyBatis是如何初始化的呢?
一:初始化的方式及引入
MyBatis的初始化可以有两种方式:
- 基于XML配置文件 -> 基于XML配置文件的方式是将MyBatis的所有配置信息放在XML文件中,MyBatis通过加载并XML配置文件,将配置文信息组装成内部的Configuration对象
- 基于Java API -> 这种方式不使用XML配置文件,需要MyBatis使用者在Java代码中,手动创建Configuration对象,然后将配置参数set 进入Configuration对象中
二:初始化方式-XML配置文件
现在就从使用MyBatis的简单例子入手,深入分析一下MyBatis是怎样完成初始化的,都初始化了什么。
// mybatis初始化
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource); // 资源 -> inputStream
// 直接
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 通过build配置构建SqlSession工厂// 通过工厂创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();// 执行SQL语句
List<Blog> list = sqlSession.selectList("com.foo.bean.BlogMapper.queryAllBlogInfo")
上述语句的作用是执行com.foo.bean.BlogMapper.queryAllBlogInfo
定义的SQL语句,返回一个List结果集。
总的来说,上述代码经历了三个阶段:mybatis初始化 -> 创建SqlSession -> 执行SQL语句
上述代码的功能是根据配置文件mybatis-config.xml 配置文件,创建SqlSessionFactory对象,然后产生SqlSession,执行SQL语句
而mybatis的初始化就发生在第三句:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
1:MyBatis初始化基本过程
SqlSessionFactoryBuilder根据传入的数据流生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例
初始化的基本过程如下序列图所示:
- 调用
SqlSessionFactoryBuilder#build(inputStream)
方法; - SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
- SqlSessionFactoryBuilder调用
XMLConfigBuilder#parse()
方法; - XMLConfigBuilder对象返回Configuration对象;
- SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
- SqlSessionFactoryBuilder返回DefaultSessionFactory对象给Client,供Client使用。
SqlSessionFactoryBuilder相关的代码如下所示:
// 1:SqlSessionFactoryBuilder#build(inputStream)的入口方法,可以看见是调用多参数的build方法
public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null);
} // 多参数build,在这里返回最后的SqlSessionFactory
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { //2. 创建XMLConfigBuilder对象用来解析XML配置文件,生成Configuration对象 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); //3. 将XML配置文件内的信息解析成Java对象Configuration对象 Configuration config = parser.parse(); //4. 根据Configuration对象创建出SqlSessionFactory对象 return build(config); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } }
}// 从此处可以看出,MyBatis内部通过Configuration对象来创建SqlSessionFactory
// 5:用户也可以自己通过API构造好Configuration对象,调用此方法创SqlSessionFactory
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config);
}
上述的初始化过程中,涉及到了以下几个对象:
对象 | 说明 |
---|---|
SqlSessionFactoryBuilder | SqlSessionFactory的构造器,用于创建SqlSessionFactory,采用了Builder设计模式 |
SqlSessionFactory | SqlSession工厂类,以工厂形式创建SqlSession对象,采用了Factory工厂设计模式 |
Configuration | 该对象是mybatis-config.xml文件中所有mybatis配置信息 |
XmlConfigParser | 负责将mybatis-config.xml配置文件解析成Configuration对象 |
2:创建Configuration对象的过程
XmlConfigParser是如何通过
parse()
方法将mybatis-config.xml配置文件解析成Configuration对象的?
2.1:将XML的信息转换为Document对象
而XML配置定义文件DTD转换成XMLMapperEntityResolver对象,然后将二者封装到XpathParser对象中
XpathParser的作用是提供根据Xpath表达式获取基本的DOM节点Node信息的操作
2.2:调用parse()方法
会从XPathParser中取出<configuration>
节点对应的Node对象,然后解析此Node节点的子Node
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; // 源码中没有这一句,只有 parseConfiguration(parser.evalNode("/configuration")); // 下面是将源码拆分为以下两句 XNode configurationNode = parser.evalNode("/configuration"); parseConfiguration(configurationNode); return configuration;
}
/** * 解析 "/configuration"节点下的子节点信息,然后将解析的结果设置到Configuration对象中 */
private void parseConfiguration(XNode root) { try { //1.首先处理properties 节点 propertiesElement(root.evalNode("properties")); //issue #117 read properties first //2.处理typeAliases typeAliasesElement(root.evalNode("typeAliases")); //3.处理插件 pluginElement(root.evalNode("plugins")); //4.处理objectFactory objectFactoryElement(root.evalNode("objectFactory")); //5.objectWrapperFactory objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); //6.settings settingsElement(root.evalNode("settings")); //7.处理environments environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 //8.database databaseIdProviderElement(root.evalNode("databaseIdProvider")); //9.typeHandlers typeHandlerElement(root.evalNode("typeHandlers")); //10.mappers mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); }
}
在上述代码中,还有一个非常重要的地方,就是解析XML配置文件子节点<mappers>
的方法mapperElements(root.evalNode("mappers"))
它将解析我们配置的Mapper.xml配置文件,Mapper配置文件可以说是MyBatis的核心
MyBatis的特性和理念都体现在此Mapper的配置和设计上
2.3:设置到Configuration对象中
各个过程就不深究了,这里就看上述的environmentsElement(root.evalNode("environments"))
方法
探究一下这个方法是如何将environments的信息解析出来,设置到Configuration对象中的
/** * 解析environments节点,并将结果设置到Configuration对象中 * 注意:创建envronment时,如果SqlSessionFactoryBuilder指定了特定的环境(即数据源); * 则返回指定环境(数据源)的Environment对象,否则返回默认的Environment对象; * 这种方式实现了MyBatis可以连接多数据源 */
private void environmentsElement(XNode context) throws Exception { if (context != null) { if (environment == null) { // 如果没有指定特定的环境,就用默认的环境配置defaultenvironment = context.getStringAttribute("default"); } for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { // 只有environment.equals(id)情况会进入//1.创建事务工厂 TransactionFactory TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); //2.创建数据源DataSource DataSource dataSource = dsFactory.getDataSource(); //3.构造Environment对象 Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); //4.将创建的Envronment对象设置到configuration 对象中 configuration.setEnvironment(environmentBuilder.build()); } } }
}// 各种特殊环境的判断
private boolean isSpecifiedEnvironment(String id) { if (environment == null) { throw new BuilderException("No environment specified."); } else if (id == null) { throw new BuilderException("Environment requires an id attribute."); } else if (environment.equals(id)) { return true; } return false;
}
最后返回Configuration对象就可以了
三:初始化方式-基于Java API
当然我们可以使用XMLConfigBuilder手动解析XML配置文件来创建Configuration对象,代码如下:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource); // resource -> inputstream // 手动创建XMLConfigBuilder,并解析创建Configuration对象,就是上面分析的源码,主动调用
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, null,null); // 看这里
Configuration configuration = parser.parse(); // 使用Configuration对象创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); // 使用MyBatis factory工厂模式先创建SqlSession,然后有了门面API,就可以操作了
SqlSession sqlSession = sqlSessionFactory.openSession();
List list = sqlSession.selectList("com.foo.bean.BlogMapper.queryAllBlogInfo");
相关文章:

Mybatis源码02 - 初始化基本过程(引导层部分)
初始化基本过程(引导层部分) 文章目录 初始化基本过程(引导层部分)一:初始化的方式及引入二:初始化方式-XML配置文件1:MyBatis初始化基本过程2:创建Configuration对象的过程2.1&…...

【Elasticsearch】bucket_sort
Elasticsearch 的bucket_sort聚合是一种管道聚合,用于对父多桶聚合(如terms、date_histogram、histogram等)的桶进行排序。以下是关于bucket_sort的详细说明: 1.基本功能 bucket_sort聚合可以对父聚合返回的桶进行排序ÿ…...

k8s证书过期怎么更新?
在 Kubernetes 集群中,证书过期可能导致集群不可用,尤其是 API Server、Controller Manager、Scheduler 等组件所使用的证书。为了恢复集群的正常运行,您需要更新这些证书。以下是更新 Kubernetes 证书的基本步骤: 1. 检查证书状…...

活动预告 |【Part 1】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁
课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动,了解如何更好地在 Microsoft 365 Defen…...

AIGC-微头条爆款文案创作智能体完整指令(DeepSeek,豆包,千问,Kimi,GPT)
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…...

C# 比较两个List集合内容是否相同
在 C# 中,要比较两个 List<T> 集合的内容是否相同,可以通过以下几种方法: 一、非自定义类的元素比较 1. 使用 SequenceEqual 方法(顺序和内容都相等) 顺序和内容都相等:使用 SequenceEqual。 usin…...

vue2 多页面pdf预览
使用pdfjs-dist预览pdf,实现预加载,滚动条翻页。pdfjs的版本很重要,换了好多版本,终于有一个能用的 node 20.18.1 "pdfjs-dist": "^2.2.228", vue页面代码如下 <template><div v-loading"loa…...

【python】matplotlib(animation)
文章目录 1、matplotlib.animation1.1、FuncAnimation1.2、修改 matplotlib 背景 2、matplotlib imageio2.1、折线图2.2、条形图2.3、散点图 3、参考 1、matplotlib.animation 1.1、FuncAnimation matplotlib.animation.FuncAnimation 是 Matplotlib 库中用于创建动画的一个…...

Hello Robot 推出Stretch 3移动操作机器人,赋能研究与商业应用
Hello Robot公司近日发布了其新一代开源移动操作机器人Stretch 3,这是一款高度灵活的机器人平台,专为机器人研究、教育实验和商业自动化设计。Stretch 3 结合了先进的移动机器人技术、灵巧操作能力和开源软件生态系统,为用户提供了一个功能强…...

从零到一:我的元宵灯谜小程序诞生记
缘起:一碗汤圆引发的灵感 去年元宵节,我正捧着热腾腾的汤圆刷朋友圈,满屏都是"转发锦鲤求灯谜答案"的动态。看着大家对着手机手忙脚乱地切换浏览器查答案,我突然拍案而起:为什么不做一个能即时猜灯谜的微信…...

Docker 安装与配置 Nginx
摘要 1、本文全面介绍了如何在 Docker 环境中安装和配置 Nginx 容器。 2、文中详细解释了如何设置 HTTPS 安全连接及配置 Nginx 以实现前后端分离的代理服务。 2、同时,探讨了通过 IP 和域名两种方式访问 Nginx 服务的具体配置方法 3、此外,文章还涵…...

Oracle常见语法
一、求交集 SELECT column1, column2 FROM table1 INTERSECT SELECT column1, column2 FROM table2;INTERSECT 操作符是 Oracle 和一些其他数据库(如 PostgreSQL 和 SQL Server)特有的集合操作符,在 MySQL 中并不直接支持。MYSQL同效果代码&a…...

在Vue3中使用Echarts的示例 两种方法
在Vue 3中使用ECharts可以通过两种主要方法实现:全局安装和组件封装。下面我将分别 介绍这两种方法的具体实现步骤。 方法1:全局安装 1.安装ECharts 在你的Vue项目中,首先需要安装ECharts。打开终端,运行以下命令: Bash copy code npm install ec…...

【docker】docker改动镜像并重新编译举例
docker改动镜像并重新编译举例 使用vllm启动Qwen VL 2.5出现报错 0.7.2 Docker Container doesnt support Qwen VL 2.5 Instruct 查看镜像 docker images 会发现本地有vllm/vllm-openai:v0.7.2镜像,id为f78c8f2f8ad5 空白文件夹中新建文件Dockerfile 写入&#…...

具身智能训练新思路!将生成视频用于训练机器人
将生成视频用于训练具身智能(Embodied AI)确实是近年来备受关注的前沿方向,这一思路通过结合生成式AI(如扩散模型、神经辐射场等)与机器人学习,为解决真实世界数据稀缺、训练成本高等问题提供了新可能。以下从技术逻辑、潜在优势、挑战及案例方向展开分析: 一、技术逻辑…...

15、深度学习-自学之路-反向传播程序展示、激活函数的应用,反向权重的更新、2层神经网络的应用,输入输出相关性的理解。
这个里面要学习和展示的内容会比较多,需要好好的认真思考 第一个要思考的就是:输入和输出相关性的理解,我们先拿一层的神经网络来说明一下, 输入有2个因素,对应有两个权重,输出有一个结果。 输入的两个因…...

【JavaEE进阶】依赖注入 DI详解
目录 🌴什么是依赖注入 🎄依赖注入的三种方法 🚩属性注⼊(Field Injection) 🚩Setter注入 🚩构造方法注入 🚩三种注⼊的优缺点 🌳Autowired存在的问题 🌲解决Autowired存在的…...

医疗影响分割 | 使用 Swin UNETR 训练自己的数据集(3D医疗影像分割教程)
<Swin UNETR: Swin Transformers for Semantic Segmentation of Brain Tumors in MRI Images> 代码地址:unetr 论文地址:https://arxiv.org/pdf/2201.01266 一、下载代码 在Github上下载代码,然后进入SWINUNETR,前两个是针对两个数据集(BRATS21、BTCV)的操作,这里…...

IGBT的两级关断
IGBT(绝缘栅双极型晶体管)的两级关断(Two-stage turn-off)是一种优化关断过程的方法,主要用于减少关断时的电压过冲和dv/dt(电压变化率)过高的问题,特别是在大功率应用中(…...

微服务与网关
什么是网关 背景 单体项目中,前端只用访问指定的一个端口8080,就可以得到任何想要的数据 微服务项目中,ip是不断变化的,端口是多个的 解决方案:网关 网关:就是网络的关口,负责请求的路由、转发…...

“云计算一哥”一口气发布6个大模型、3nm芯片!多模态还要搞Any-to-Any
金磊 发自 拉斯维加斯量子位 | 公众号 QbitAI 就在刚刚,云计算一哥亚马逊云科技,在大模型这件事儿上搞了波大的—— 亚马逊CEO Andy Jassy亲自站台re:Invent24,发布自家新款AI多模态系列大模型,名曰Amazon Nova。 而且是一口气涵盖…...

pytest生成报告no tests ran in 0.01s
除了基本的环境配置、用例名要以test_开头,有个地方是我自己忽略了,在执行时没有指定用例文件,所以没有找到。 if __name__ __main__:pytest.main(["testcases/test_demo.py","-svq", __file__, --alluredir./allure-r…...

如何修改DNS解析?
DNS(域名系统)就像互联网的“电话簿”,负责将我们输入的网址转换为计算机能够理解的IP地址。如果DNS解析出现问题,访问网站就会受到影响。那我们该如何修改DNS解析呢?接下来,我们就来介绍一下这个话题。 为什么要修改DNS解析? 使用默认的…...

PyTorch 中 `torch.cuda.amp` 相关警告的解决方法
在最近的写代码过程中,遇到了两个与 PyTorch 的混合精度训练相关的警告信息。这里随手记录一下。 警告内容 警告 1: torch.cuda.amp.autocast FutureWarning: torch.cuda.amp.autocast(args...) is deprecated. Please use torch.amp.autocast(cuda, args...) i…...

微服务组件LoadBalancer负载均衡
SpringCloud 从 2020.0.1 版本开始,移除了 Ribbon 组件,使⽤Spring Cloud LoadBalancer 组件来代 替 Ribbon 实现客户端负载均衡 loadbalancer负载均衡: 复制一份provider项目,服务名一致,端口号不一致,让consumer调…...

如何本地部署DeepSeek
第一步:安装ollama https://ollama.com/download 打开官网,选择对应版本 第二步:选择合适的模型 https://ollama.com/ 模型名称中的 1.5B、7B、8B 等数字代表模型的参数量(Parameters),其中 B 是英文 B…...

vite + axios 代理不起作用 404 无效
vite axios 代理不起作用 先看官方示例 export default defineConfig({server: {proxy: {// 字符串简写写法/foo: http://localhost:4567,// 选项写法/api: {target: http://jsonplaceholder.typicode.com,changeOrigin: true,rewrite: (path) > path.replace(/^\/api/, )…...

centos7 升级openssl并安装python3
参考文章:https://www.cnblogs.com/chuanzhang053/p/17653635.html 卸载已有版本 yum remove -y openssl openssl-devel下载1.1版本 wget https://www.openssl.org/source/openssl-1.1.1v.tar.gztar -zxf openssl-1.1.1v.tar.gz 查看openssl.conf文件的目录 fin…...

使用 SDKMAN! 在 Mac(包括 ARM 架构的 M1/M2 芯片)上安装 Java 8
文章目录 1. 安装 SDKMAN!2. 查找可用的 Java 8 版本3. 安装 Java 84. 验证安装5. 切换 Java 版本(可选)6. 解决 ARM 架构兼容性问题总结 可以使用 SDKMAN! 在 Mac(包括 ARM 架构的 M1/M2 芯片)上安装 Java 8。SDKMAN! 是一个强大…...

【干活分享】2025年可以免费问答的一些GPT网站-deepseek等免费gpt
2025年已经到来,大家也都陆续回归到忙碌的工作中。在新的一年里,如何更高效地完成工作任务,提升工作效率,是很多人关心的问题。今天,就为大家分享一些实用性很强的GPT网站,帮助大家在工作中事半功倍。 Dee…...