网易首页 > 网易号 > 正文 申请入驻

Mybatis中SqlSource解析流程详解

0
分享至

前面几篇文章都在详细分析mapper的加载过程,但是始终没有看到sql的解析过程,今天来详细分析下。

解析sql的位置

前面分析到不管是通过注解还是通过xml方式生成mapper,最终都是调用MapperBuilderAssistant类的addMappedStatement方法,这个方法接受的其中一个SqlSource参数,SqlSource类中就是XML文件或者注解方法中映射语句的实现

那么SqlSource对象是在哪里创建的呢?

在通过注解实现mapper的流程中是在MapperAnnotationBuilder类的parseStatement方法中对SqlSource进行初始化,初始化代码如下图:

通过xml文件实现mapper的流程中是在XMLStatementBuilder类的parseStatementNode方法中对SqlSource进行初始化,初始化代码如下图:

可以看到创建SqlSource对象都是通过LanguageDriver实现的,翻译过来叫做语言驱动,它是一个接口,通过上面源码可以看出来我们可以自己实现这个接口,并且可以指定使用哪个语言驱动。今天我们只关注mybatis自带的一个实现XMLLanguageDriver。

XMLLanguageDriver介绍

XMLLanguageDriver类有重载了两个createSqlSource方法,主要区别在于第二个参数script,从前面两张源码图中可以知道接受XNode类型的script是在解析xml时使用,接受String类型的script是在解析注解时使用,今天只解析接受XNode类型的方法。

这个方法比较简单只有两步:初始化一个XMLScriptBuilder对象,执行XMLScriptBuilder对象的parseScriptNode方法。所以重点来到XMLScriptBuilder这个类。

XMLScriptBuilder详解

XMLScriptBuilder类部分源码如下图:

XMLScriptBuilder的初始化比较简单,要记住XNode context对应的是xml中的一个select、update等节点,在最后调用了initNodeHandlerMap方法设置了select、update等节点子节点对应的处理器。

接着是parseScriptNode方法,可以看到parseScriptNode方法调用了parseDynamicTags方法生成了一个MixedSqlNode对象,然后根据属性isDynamic判断创建对应的SqlSource对象。

所以最终要看parseScriptNode方法,同时可以判断isDynamic这个属性肯定也会在这个方法中发生变化,parseScriptNode方法的源码如下图:

parseDynamicTags方法解析节点下面所有子节点进行遍历,如果节点是文本节点这解析里面的内容生成SqlNode(这里是TextSqlNode或者StaticTextSqlNode)对象放到contents集合中。

如果是脚本节点比如where、if等就调用初始化时保存的节点处理器,如上图的ForEachHandler、IfHandler处理器,这些对象的处理方法handleNode的第一行代码又在调用parseDynamicTags方法,就像是一种递归。所以我们可以得出xml中的where、if、foreach这些节点可以彼此包含的,解析时再进行递归解析

当然要想调用parseDynamicTags方法,这些对象都是属于当前类XMLScriptBuilder的内部类。

大的方向梳理了我们再来看这个方法到底在干什么,首先这个方法会收集SqlNode对象放到contents集合中,最后把contents作为参数生成MixedSqlNode对象。在处理的过程中如果遇到if、foreach等节点还会把contents传递进去,从上面的图中可以看到ForEachHandler、IfHandler处理器也会调用parseDynamicTags方法生成MixedSqlNode然后再生成对应的SqlNode放到contents中。

所以最终来到两个关键类MixedSqlNode、SqlNode,当然SqlNode肯定有各种子类。

MixedSqlNode与SqlNode

那么MixedSqlNode与SqlNode是什么样子的呢?又是如何组合的?具体源码如下图:

可以看到SqlNode是一个接口,而MixedSqlNode只是他的一种实现类,同时来贴出来了静态文本处理的类和if节点对应的IfSqlNode类,还有一些其他比如WhereSqlNode、ForEachSqlNode等就不再列出来了。

每一种实现类的初始化都比较简单,比如StaticTextSqlNode是保存一段文本,IfSqlNode保存了if节点的test属性对应的值和从if节点下解析出来的MixedSqlNode节点。

而他们有一个由SqlNode规定的apply方法,这才是他们正真的作用所在,比如MixedSqlNode是遍历所有节点执行对应的apply方法,StaticTextSqlNode就只是把对应sql拼接到后面,IfSqlNode是在进行判断后调用MixedSqlNode去执行if节点下所有的节点。

至于参数DynamicContext后面在调用的时候会分析的。

现在回到XMLScriptBuilder的parseScriptNode方法,方法在执行了parseDynamicTags方法后根据isDynamic属性初始化了SqlSource,对应类结构图如下图:

我们主要关注DynamicSqlSource这个类,可以看到它就两个属性configuration、rootSqlNode,分别是全局配置和刚刚分析的MixedSqlNode,也可以从他的getBoundSql方法中看到后面对rootSqlNode的使用,这个留着后面分析。

总结

在configuration中有一个map属性mappedStatements,他保存着MappedStatement对象,每个MappedStatement对象对应一个sql的所有信息,而MappedStatement也有一个属性SqlSource,通过SqlSource能够获取到对应的sql,而sql的解析时依靠SqlNode。

今天的重点就在于生成SqlNode的过程,它是通过XMLScriptBuilder类是处理xml中crud节点生成。

这里有意思的是设计时是XMLScriptBuilder自带处理节点的方法parseDynamicTags生成需要的MixedSqlNode,而在parseDynamicTags方法内部可能会调用内部类WhereHandler、IfHandler的handleNode方法生成对应的SqlNode,而在这些handleNode方法中第一步就是调用parseDynamicTags去生成MixedSqlNode,根据MixedSqlNode生成对应的SqlNode。通过这种递归实现了节点多层嵌套的解析

第二个有意思的点在于SqlNode的框架设计,MixedSqlNode存储一个SqlNode的集合,而具体的比如IfSqlNode又可以持有SqlNode,通过这样实现,每种SqlNode都可以拥有所有各种的SqlNode功能,但是他们有拥有自己独立的特点。

正是XMLScriptBuilder和SqlNode这种灵活的设计才可以使xml标签有非常强大的支持,同时解析的时候又不至于太复杂。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
医保起付线到底咋回事?2026年新规全拆解,看懂一年能省大几千!

医保起付线到底咋回事?2026年新规全拆解,看懂一年能省大几千!

老特有话说
2026-01-25 23:19:27
罪有应得!官方彻查后,闫学晶再迎噩耗,她最担心的事还是发生了

罪有应得!官方彻查后,闫学晶再迎噩耗,她最担心的事还是发生了

来科点谱
2026-01-23 11:08:02
38+33+32+30!回来了!NBA第一攻击型大中锋

38+33+32+30!回来了!NBA第一攻击型大中锋

篮球实战宝典
2026-01-25 18:10:46
大寒吃三鲜,一年病不沾!大寒时节记得吃这3鲜,暖身抗寒迎新春

大寒吃三鲜,一年病不沾!大寒时节记得吃这3鲜,暖身抗寒迎新春

江江食研社
2026-01-25 14:30:03
董路登上日本网站热搜榜第一,日本网友:中国足球专家何时成熟?

董路登上日本网站热搜榜第一,日本网友:中国足球专家何时成熟?

杨华评论
2026-01-25 20:51:07
29岁女子被丈夫砍死!受害者完全可以逃生,3条生路被堵死

29岁女子被丈夫砍死!受害者完全可以逃生,3条生路被堵死

细品名人
2026-01-26 07:36:25
全球销量六连冠!嘲讽丰田不行了的人,非蠢即坏

全球销量六连冠!嘲讽丰田不行了的人,非蠢即坏

象视汽车
2026-01-24 07:00:03
-5℃,广东男子穿短袖爬云冰山

-5℃,广东男子穿短袖爬云冰山

半岛晨报
2026-01-26 12:30:03
王祖贤缺钱了!下体2cm男星亲妈被举报!

王祖贤缺钱了!下体2cm男星亲妈被举报!

八卦疯叔
2026-01-26 13:22:51
女留学生回国就诊“肛裂”!网友:公司现招聘海龟要体检生殖系统

女留学生回国就诊“肛裂”!网友:公司现招聘海龟要体检生殖系统

火山诗话
2026-01-24 07:32:05
后悔也晚了!大批F35逼到家门口,伊朗却发现红旗9和歼10还未到位

后悔也晚了!大批F35逼到家门口,伊朗却发现红旗9和歼10还未到位

阿器谈史
2026-01-25 00:15:57
锡安两双力挽狂澜,文班亚马空砍16+16+4封盖,马刺不敌西部倒一

锡安两双力挽狂澜,文班亚马空砍16+16+4封盖,马刺不敌西部倒一

钉钉陌上花开
2026-01-26 10:26:59
“美航母逼近”,伊朗挂起巨幅画…

“美航母逼近”,伊朗挂起巨幅画…

观察者网
2026-01-26 15:30:04
杨鸣仍担任辽宁省篮协职务

杨鸣仍担任辽宁省篮协职务

雷达财经
2026-01-26 11:15:03
最高160万!上海一法院发布悬赏公告

最高160万!上海一法院发布悬赏公告

上观新闻
2026-01-25 22:07:10
霍诺德玩命攀登101大楼酬劳曝光,回应:尴尬的小数目

霍诺德玩命攀登101大楼酬劳曝光,回应:尴尬的小数目

体育妞世界
2026-01-25 16:35:37
中国哪的酱油最好吃?经评比,这6种酱油榜上有名,你喜欢哪种?看看有没有你家乡?

中国哪的酱油最好吃?经评比,这6种酱油榜上有名,你喜欢哪种?看看有没有你家乡?

美食格物
2026-01-26 14:06:13
“去鲁迅化” 已 10 年有余,究竟要去什么?莫言余华看法一致

“去鲁迅化” 已 10 年有余,究竟要去什么?莫言余华看法一致

小豫讲故事
2026-01-23 06:00:04
一个拿腔作势一个双目无神,两人连累48集大剧,老戏骨再强也没用

一个拿腔作势一个双目无神,两人连累48集大剧,老戏骨再强也没用

查尔菲的笔记
2026-01-24 20:12:13
国安部披露:个别社交平台账号打着“历史科普”的旗号,通过未经核实的内容、渲染阴谋论等方式歪曲事实,企图让网民陷入历史虚无主义陷阱

国安部披露:个别社交平台账号打着“历史科普”的旗号,通过未经核实的内容、渲染阴谋论等方式歪曲事实,企图让网民陷入历史虚无主义陷阱

扬子晚报
2026-01-26 07:17:27
2026-01-26 16:07:00
IT乐知
IT乐知
it乐知· 程序员的私房笔记
122文章数 1038关注度
往期回顾 全部

科技要闻

印奇再上牌桌,阶跃融资50亿

头条要闻

高市早苗:若执政党阵营在选举中未过半数 将即刻辞职

头条要闻

高市早苗:若执政党阵营在选举中未过半数 将即刻辞职

体育要闻

叛逆的大公子,要砸了贝克汉姆这块招牌

娱乐要闻

张雨绮被实名举报代孕、插足婚姻

财经要闻

从美式斩杀线看中国社会的制度韧性构建

汽车要闻

宾利第四台Batur敞篷版发布 解锁四项定制创新

态度原创

数码
艺术
游戏
公开课
军事航空

数码要闻

探索非显示业务:消息称LG Display正开发半导体玻璃中介层

艺术要闻

溥心畬的花鸟,淡雅清新

《轮回之兽》惊艳?GF谈性能表现:心意比帧数更重要

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

委代总统称遭美威胁:马杜罗已死

无障碍浏览 进入关怀版