mybatis源码分析之XMLConfigBuilder对XML文件的解析

XMLConfigBuilder对XML文件的解析

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

parse.parse()是解析xml的开端。

/**
   * 解析配置文件的入口方法
   * @return Configuration对象
   */
  public Configuration parse() {
    // 不允许重复解析
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    // 从根节点开展解析
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

parseConfiguration(parser.evalNode("/configuration"));
就是利用XPather中包含的jdk提供的XPath类对xml文件进行解析。

关于XPath的语法:

DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
       DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
       Document doc = documentBuilder.parse(Resources.getResourceAsFile("conf/mapperTest.xml"));

       XPathFactory xPathFactory = XPathFactory.newInstance();
       XPath xPath = xPathFactory.newXPath();
       String name = (String) xPath.evaluate("/configuration/properties/property[1]/@name", doc, XPathConstants.STRING);
       String value = (String) xPath.evaluate("/configuration/properties/property[1]/@value", doc, XPathConstants.STRING);
       System.out.println(name);
       System.out.println(value);

现在我们进入parser.evalNode("/configuration")去看看怎么执行的。

public XNode evalNode(String expression) {
    return evalNode(document, expression);
  }

  public XNode evalNode(Object root, String expression) {
    Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
    if (node == null) {
      return null;
    }
    return new XNode(this, node, variables);
  }
  
  /**
   * 进行XML节点的解析
   * @param expression 解析的语句
   * @param root 解析根
   * @param returnType 返回值类型
   * @return 解析结果
   */
  private Object evaluate(String expression, Object root, QName returnType) {
    try {
      // 对指定节点root运行解析语法expression,获得returnType类型的解析结果
      return xpath.evaluate(expression, root, returnType);
    } catch (Exception e) {
      throw new BuilderException("Error evaluating XPath.  Cause: " + e, e);
    }
  }

我们在看看XNode具体是什么东西

public class XNode {

  // org.w3c.dom.Node 表示是xml中的一个节点
  private final Node node;
  // 节点名
  private final String name;
  // 节点体
  private final String body;
  // 节点的属性
  private final Properties attributes;
  //  MyBatis配置文件中的properties信息
  private final Properties variables;
  // XML解析器XPathParser
  private final XPathParser xpathParser;

  public XNode(XPathParser xpathParser, Node node, Properties variables) {
    this.xpathParser = xpathParser;
    this.node = node;
    this.name = node.getNodeName();
    this.variables = variables;
    this.attributes = parseAttributes(node);
    this.body = parseBody(node);
  }
  
  private Properties parseAttributes(Node n) {
    Properties attributes = new Properties();
    NamedNodeMap attributeNodes = n.getAttributes();
    if (attributeNodes != null) {
      for (int i = 0; i < attributeNodes.getLength(); i++) {
        Node attribute = attributeNodes.item(i);
        String value = PropertyParser.parse(attribute.getNodeValue(), variables);
        attributes.put(attribute.getNodeName(), value);
      }
    }
    return attributes;
  }

很显然,这是一个mybatis自己写的增强版的Node,这个XNode的参数Node保存了该节点的信息,并用attributes保存节点属性名称和值的对应,用variables保存了Properties的信息。

    <properties resource="conf/config.properties">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </properties>
  • 以properties来说明,attributes保存节点属性名称和值的对,即保存了resource=conf/config.properties。
  • 以property来说明,则保存了两个键值对,name=driver和value=${driver}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值