xml如何循环解析相同节点的第二个字段_Mybatis中SqlSource解析流程详解

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

解析sql的位置

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

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

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

2b7a769085b19517d7f3481b84e025c8.png

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

60c6f134eabf69d982a91645ed3817bf.png

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

XMLLanguageDriver介绍

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

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

XMLScriptBuilder详解

XMLScriptBuilder类部分源码如下图:

c3048b10b70415716b9c1020bc4b63b7.png

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

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

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

20fcf9b0e7fa8d17fd1c2e5deb95778e.png

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肯定有各种子类。

MixedSqlNodeSqlNode

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

f7cdabcda2d46a23c465045bad7c9faf.png

可以看到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,对应类结构图如下图:

0505611e57a2d073518120d385f3bd8c.png

我们主要关注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程序员日常学习笔记,如理解有误欢迎各位交流讨论!

c5d8065135737a63d4f63fc4365b5404.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值