当前位置: 首页 > news >正文

【12.MyBatis源码剖析与架构实战】15.1 if和where标签执⾏过程剖析-初始化时

在 MyBatis 中,<if><where>标签在初始化阶段被解析为IfSqlNodeWhereSqlNode对象,并纳入语法树。下面将从入口调用NodeHandler 注册机制标签处理逻辑三个层面,结合底层源码和流程图进行剖析。

一、初始化阶段入口:从 XMLScriptBuilder 开始

MyBatis 启动时通过XMLScriptBuilder.parseDynamicTags()方法解析 SQL 节点。该方法接收一个 XNode 参数(代表整个<select><insert>等 SQL 语句节点),遍历其所有子节点,将文本节点和元素节点分别转换为对应的 SqlNode 对象,存入List<SqlNode>集合中,最终包装为MixedSqlNode作为语法树的根节点。

核心判断逻辑如下:

  • 文本节点:直接封装为StaticTextSqlNode(静态文本)或TextSqlNode(含${}的动态文本)。
  • 元素节点:通过节点名称(如ifwhereforeach)从nodeHandlerMap中获取对应的NodeHandler处理,一旦遇到任何元素节点,就标记isDynamic = true,最终创建DynamicSqlSource

二、NodeHandler 注册机制

XMLScriptBuilder在构造时会调用initNodeHandlerMap()方法,将所有动态标签与对应的NodeHandler实现类进行映射绑定:

// XMLScriptBuilder.initNodeHandlerMap()Map<String,NodeHandler>map=newHashMap<>();map.put("trim",newTrimHandler());map.put("where",newWhereHandler());map.put("set",newSetHandler());map.put("foreach",newForEachHandler());map.put("if",newIfHandler());map.put("choose",newChooseHandler());// ...

当解析到where节点时,nodeHandlerMap.get("where")返回WhereHandler;解析到if节点时,返回IfHandler。这种设计使得新增动态标签只需增加一个NodeHandler实现并注册即可,符合开闭原则

三、WhereHandler:解析 标签

WhereHandlerXMLScriptBuilder的内部类,负责处理<where>标签:

privateclassWhereHandlerimplementsNodeHandler{publicWhereHandler(){}@OverridepublicvoidhandleNode(XNodenodeToHandle,List<SqlNode>targetContents){// 1. 递归解析 <where> 节点内部的子内容,生成 MixedSqlNodeMixedSqlNodemixedSqlNode=parseDynamicTags(nodeToHandle);// 2. 创建 WhereSqlNode,将 mixedSqlNode 作为其内部 contentsWhereSqlNodewhere=newWhereSqlNode(configuration,mixedSqlNode);// 3. 将 WhereSqlNode 添加到父级 contents 列表中targetContents.add(where);}}

核心流程:

  1. 递归解析:调用parseDynamicTags(nodeToHandle)解析<where>标签内部的 SQL 片段(如<if>标签和静态文本),生成一个MixedSqlNode
  2. 构建 WhereSqlNode:将MixedSqlNode作为构造参数传入WhereSqlNodeWhereSqlNode本质上是TrimSqlNode的子类,预设了前缀"WHERE"以及需要覆盖的前缀列表AND |OR
  3. 挂载到父级:将创建好的WhereSqlNode添加到targetContents中,成为语法树的一部分。

四、IfHandler:解析 标签

IfHandler同样定义在XMLScriptBuilder内部,负责处理<if test="...">标签:

privateclassIfHandlerimplementsNodeHandler{@OverridepublicvoidhandleNode(XNodenodeToHandle,List<SqlNode>targetContents){// 1. 递归解析 <if> 节点内部的子内容,生成 MixedSqlNodeMixedSqlNodemixedSqlNode=parseDynamicTags(nodeToHandle);// 2. 获取 test 属性值Stringtest=nodeToHandle.getStringAttribute("test");// 3. 创建 IfSqlNodeIfSqlNodeifSqlNode=newIfSqlNode(mixedSqlNode,test);// 4. 将 IfSqlNode 添加到父级 contents 列表中targetContents.add(ifSqlNode);}}

核心流程:

  1. 递归解析:同样调用parseDynamicTags(nodeToHandle)解析<if>内部的 SQL 片段,生成MixedSqlNode
  2. 获取条件表达式:从 XML 节点中读取test属性值(OGNL 表达式),用于运行时条件判断。
  3. 构建 IfSqlNode:将解析得到的MixedSqlNodetest表达式传入构造器。IfSqlNode在运行时通过ExpressionEvaluatortest表达式求值,决定是否将内部 SQL 片段拼接到最终 SQL 中。
  4. 挂载到父级:将IfSqlNode添加到父级contents列表中。

五、完整解析流程 UML 流程图

http://www.jsqmd.com/news/657837/

相关文章:

  • 从GKCTF 2021 XOR题解看异或运算在密码学中的巧妙应用与比特爆破实战
  • 从冠军方案拆解:在Jane Street预测赛中,如何用AE+MLP+XGBoost玩转模型融合?
  • AI辅助排版:设计领域的应用方法与落地实践
  • 西门子S7-1200 PLC控制三相六拍步进电机:从梯形图到实物接线保姆级教程
  • 旧显示器秒变智能投屏屏!树莓派4B双协议(Miracast+AirPlay)无线投屏器完整配置指南
  • 如何三步解锁WeMod Pro功能:Wand-Enhancer终极指南
  • 别再让Copilot绕过你的Security Gate!:实时拦截高危生成代码的eBPF+LLM Guard联合审查方案(已通过ISO 27001渗透验证)
  • FastGPT 架构深度分析
  • STM32新手必看:GPIO初始化失败,别再用RCC_AHBPeriphResetCmd了!
  • 不止于分词:用SpringBoot+HanLP 1.7.7快速构建一个简易文本分析服务
  • 数据库基础概念与体系结构 - 软考备战(二十九)
  • Tiny-ViT: A Compact Vision Transformer for Efficient and Explainable Potato Leaf Disease Classificat
  • 011、算子中间表示概述:计算图与算子抽象
  • YOLO+ByteTrack路口违章抓拍实战:多目标稳定追踪与违章判定
  • 2026年软件测试工具TOP 10选型指南:趋势洞察与实战决策
  • Android音频调试实战:用dumpsys media.audio_flinger揪出音频卡顿的元凶
  • 如何把MAX31865的精度榨干?STM32驱动PT100三线制测温的校准与优化实战
  • 多SKILL协同推理:双慢病联合决策:SKILL架构下糖尿病与高血压的协同诊疗体系.147
  • 新能源汽车整车控制器VCU学习模型:初学者的快速入门指南
  • 智能代码生成风格一致性落地指南(2024企业级实践白皮书)
  • 012、张量与数据布局:内存模型与对齐策略
  • 从Urbannav真值话题到NavSatFix:手把手教你转换GPS数据格式用于ROS定位评估
  • 2026最权威的AI科研网站推荐
  • 智能排版:核心功能解析与效率提升实践指南
  • Java雪花算法实战:从原理剖析到高并发场景下的ID生成器实现
  • 保姆级教程:用Python和COCO API搞定MSCOCO数据集下载、解析与可视化
  • 016、LangChain进阶:Memory、Retriever与工程化组织,才是你真正该补的部分
  • 从UML到LLM,AI设计模式生成全链路拆解,深度解析SITS2026现场验证的8项关键指标
  • 告别裸机调试:在ZYNQ上为自定义AXI-Stream IP核编写PS端驱动的心路历程
  • 小智AI融合火山引擎ASR:实战双向流式与智能负载均衡架构