MyBatis|解析器模块

概述

解析器模块主要提供了两个功能:

  • 对 XPath 进行封装,为 MyBatis 初始化时解析 mybatis-config.xml 配置文件以及映射文件提供支持「使用过 MyBatis 都知道,需要配置文件以及 Mapper.xml 映射文件,而加载解析这些配置就是这个模块提供的支持」
  • 为处理动态 SQL 语句中的占位符提供支持「我们使用 #{} 占位符时的处理」

XPathParser

是 MyBatis 基于 Java XPath 封装的解析器,用于 mybatis-config.xml 以及 Mapper.xml 文件的解析。

属性解析

  private final Document document;  
  private boolean validation; //
  private EntityResolver entityResolver; //
  private Properties variables; //
  private XPath xpath; //
复制代码
  • document : org.w3c.dom.Document; Java 自带的 Document 对象
  • validation: 是否开启验证,是否校验 XML,一般是 true
  • entityResolver: 用于加载本地 DTD 文件,防止从网络上获取 DTD 文件加载,避免网络不稳定的情况
  • variables: mybatis-config 中 标签定义的键值对集合
  • xpath: XPath 对象,也是Java 自带的,用于查询 XML 中的节点和元素。

构造函数

它里面有很多构造函数,随便选一个看看:

  public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
    commonConstructor(validation, variables, entityResolver);
    this.document = createDocument(new InputSource(inputStream));
  }
复制代码
  • commonConstructor() 方法就是对 XPathParser 属性的初始化
  • createDocument 从配置文件中获取 Document 对象

其中 entityResolver ,如果我们去 XMLConfigBuilder 类文件中,就会发现:里面的是 XMLMapperEntityResolver(),里面的核心方法是 resolveEntity :就是加载本地的 dtd 文件。

  public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
  }
复制代码

eval* 方法

里面提供了很多 eval* 的方法,用于获得 Boolean、Short、Integer、Long、Float、Double、String、Node 类型的元素或节点的值。但是他们都是基于 evaluate(String expression,Object root,QName returnType)方法。

//获取指定元素或节点的值
private Object evaluate(String expression, Object root, QName returnType) {
    try {
      return xpath.evaluate(expression, root, returnType);
    } catch (Exception e) {
      throw new BuilderException("Error evaluating XPath.  Cause: " + e, e);
    }
  }
复制代码

GenericTokenParser

上面的 XPathParser#evalString() 也是会生成此对象进行解析的。

这是一个通用的 Token 解析器,里面就一个 parse 解析方法:它会顺序查找 opentoken、closetoken ,解析得到占位符的字面值,并将其交给 TokenHandler 处理,然后将解析结果重新拼装成字符串返回。

代码我就不贴了,可以直接去源码中搜索看看。

PropertyParser

动态属性解析器。

里面构造函数是静态的,提供了静态的 parse 解析方法。

  public static String parse(String string, Properties variables) {
    VariableTokenHandler handler = new VariableTokenHandler(variables);
    GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
    return parser.parse(string);
  }
复制代码

其中制定了 TokenHandler 实现类:VariableTokenHandler ;然后 解析是占位符是 ${}。

TokenHandler

token 处理器接口,里面有四个实现方法。有点策略模式的意思。上面的 PropertyParser 里面有一个静态内部类:就是此接口的实现:VariableTokenHandler。

总结

  1. 解析 XML 的类:XPathParser 是基于 Java rt.jar 包里面的内容 org.w3c.dom、org.xml.sax、javax.xml 一般都是直接使用,一般平时使用的更多的是 dom4j 这个 jar 包。
  2. GenericTokenParser#parse 方法,主要就是替换占位符,自己开发中也写过这种解析方法,但是就一个方法完事,不像这里的方法边界考虑的很好,而且使用了策略模式将不同的处理分到具体的实现类。框架的设计就是吊。

参考

  • 徐郡明 《MyBatis 技术内幕》「2.1 解析器模块」

猜你喜欢

转载自juejin.im/post/7230308610080194616