Mybatis源码阅读之五——Java的XML解析

【系列目录】
Mybatis源码阅读之一——工厂模式与SqlSessionFactory

Mybatis源码阅读之二——模板方法模式与Executor

Mybatis源码阅读之三——JDBC解析与Mybatis封装

Mybatis源码阅读之四——装饰器模式与Mybatis中的各种Cache

【本文目录】


系列的前几篇中,我们从Mybatis使用的角度一步步深入到源码,今天从另一个角度,来看一下Mybatis资源的加载流程。

Mybatis中,Sql的模板编写有两种方式,一个是xml,另一种是注解。其中xml方式是最早出现的,也是支持最全面的。

一. XML

可扩展标记语言,标准通用标记语言的子集,简称XML。是一种用于标记电子文件使其具有结构性的标记语言。

从概念中我们能获取几个关键字:

  • 标记语言
    什么是标记语言?通俗的理解,就是给一堆五结构化的数据以结构。比如HTML,HTML提供了各种各样的标签,用于协议一个结构框架。
  • 可扩展
    标记语言如HTML是不可扩展的,他的标签固定,除非升级HTML版本否则无法增加其他的标签,这就是不可扩展,而XML则解决了这一问题,是可扩展的。

XML可扩展的关键,就在于它有一个定义自己结构的“元标签定义”,那就是DTD。

DTD

DTD提供了一系列合法的元素来定义文档的结构,如下图所示,是Mybatis定义的DTD文件,用于定义Mapper的xml中的标签语法。

XML语法

XML文档呈现树状结构,从root节点开始,一层层的子节点填充在里面,这其中,有一些语法规则:

  • 有且只有一个根元素
  • Xml文档声明必须放在文档第一行
  • 所有标签必须成对出现
  • Xml标签严格区分大小写
  • XML必须正确嵌套
  • XML中的属性值必须加引号
  • XML中,一些特殊字符需要使用实体,比如小于号要使用<来代替。

二. JAVA官方的xml解析-DOM

JAVA官方提供了对xml解析的方法,在rt包的java.xml下:

使用案例

下面使用java的xml包来解析一个我们自定义的xml:

  • xml文件
    在这里插入图片描述

  • 解析代码

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;

public class A2 {
  public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
    InputStream input = A2.class.getResourceAsStream("./mybatis-config.xml");
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(input);

    printNode(doc.getFirstChild(),0);
  }
  static void printNode(Node n, int indent) {
    for (int i = 0; i < indent; i++) {
      System.out.print(' ');
    }
    switch (n.getNodeType()) {
      case Node.DOCUMENT_NODE: // Document节点
        System.out.println("Document: " + n.getNodeName());
        break;
      case Node.ELEMENT_NODE: // 元素节点
        System.out.println("Element: " + n.getNodeName());
        break;
      case Node.TEXT_NODE: // 文本
        System.out.println("Text: " + n.getNodeName() + " = " + n.getNodeValue());
        break;
      case Node.ATTRIBUTE_NODE: // 属性
        System.out.println("Attr: " + n.getNodeName() + " = " + n.getNodeValue());
        break;
      default: // 其他
        System.out.println("NodeType: " + n.getNodeType() + ", NodeName: " + n.getNodeName());
    }
    for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
      printNode(child, indent + 1);
    }
  }
}
  • 展示结果

由上面的案例我们能够认识到xml是一个树形结构的数据,因此我们需要使用循环/嵌套/递归等方式来解析,那么有没有另外一种手段,能够更简洁直接的从这个树形结构中获取实际数据呢?

XPath

XPath 是一门在 XML 文档中查找信息的语言。

  • XPath基本语法
表达符含义
nodename选取此节点的所有子节点。
/从根节点选取(取子节点)。
//从匹配选择的当前节点选择文
档中的节点,而不考虑它们的
位置(取子孙节点)。
.选取当前节点。
选取当前节点的父节点。
@选取属性。
  • 语法示例(以上述demo为案例)
    选取Mybatis下的title标签:/mybatis/title
    选取mybatis下的names中的第一个name标签:/mybatis/names/name[1]

  • java实现
    只需要在上述demo中增加java.xml提供的Xpath实例,即可使用Xpath功能。

三. Mybatis的xml解析

回顾之前我们使用Mybatis的方式Mybatis源码阅读之一——工厂模式与SqlSessionFactory,在SqlSessionFactory的各种重载的构建方法中,都会走到这么一个逻辑中。

解析初始化配置文件

  • 构建XMLConfigBuilder
  • XMLConfigBuilder构造
  • XPathParser构造
    这里只做了两件事情:
    • 生成一个xpath解析器
    • 生成一个mybatis配置文件的document对象。
  • 回到SqlSessionFactoryBuilder.build中,得到XMLConfigBuilder对象后会进行parse操作。
  • XMLConfigBuilder.parse
  • parser.evalNode("/configuration")
    解析mybatis配置文件顶层节点,将java.xml解析器得到的Node结果进行封装,得到自定义的XNode对象。
  • 回到XMLConfigBuilder.parseConfiguration
    获取到根节点后,解析里面的各种配置(包括数据源配置):
    其中mapperElement方法则会涉及到我们自己的mapper xml文件解析。
  • XMLConfigBuilder.mapperElement

    我们有时因为Mapper和Mapper xml对应不上导致的异常也会在(初始化过程的)这个地方报出来。

到这里,也就是Mybatis使用xml的大致过程,DefaultSqlSessionFactory的初始化过程已经讲解完毕。
在mybatis配置解析中有一个核心配置——datasource:
接下来,我们分析一下Mybatis的数据库连接池实现以及同时下热门三方连接池的比较。


欢迎关注微信公众号 【JAVA技术分享官】,公众号首发,持续输出原创高质量JAVA开发者知识点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值