MyBatis如何解析mapper.xml中的sql相关信息(一)

在日常的解析XML文件有四中主流的方法,DOM解析,SAX解析,JDOM解析,DOM4j解析,那么在Mybatis中用到了DOM的解析方法,JDOM和DOM4j是开源jar包,其中DOM4j运用的较多,性能较好,我们可以日后研究学习他的解析细节。

在Mybatis的解析中它自己新写了一个类XNode的节点类,了解xml解析的不难理解它意义。

现在开始从源码看起,首先从下面加载代码中找到入口

//config.xml配置文件,没有整合spring,mapper.xml都在配置文件里的mappers标签中
Reader reader = Resources.getResourceAsReader("/config.xml"); 
            SqlSessionFactory sq = new SqlSessionFactoryBuilder().build(reader);

进入到build()方法后,定位到这里的build()方法,finally部分源码删除了,占地方。。

 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } 
        return var5;
    }

方法里的三个参数分别是,配置文件流,其他参数俩都为空,首先是构造了XMLConfigBuilder类的构造方法,到这个构造方法看一下

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

继续跳XPathParser类的构造方法

 public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
        this.commonConstructor(validation, variables, entityResolver);
        this.document = this.createDocument(new InputSource(reader));
    }

首先commonConstructor方法简单的操作后,this.createDocument()方法看一下

private Document createDocument(InputSource inputSource) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(this.validation);
            factory.setNamespaceAware(false);
            factory.setIgnoringComments(true);
            factory.setIgnoringElementContentWhitespace(false);
            factory.setCoalescing(false);
            factory.setExpandEntityReferences(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver(this.entityResolver);
            builder.setErrorHandler(new ErrorHandler() {
               //...省略了。
            });
            return builder.parse(inputSource);
        } catch (Exception var4) {
            throw new BuilderException("Error creating document instance.  Cause: " + var4, var4);
        }
    }

这里明显看到了try的第一行代码:DocumentBuilderFactory.newInstance();随后又
return builder.parse(inputSource); 说明讲Mybatis配置文件流进行了JDK的DOM解析后返回一个Document对象。

这时候我们再回到SqlSessionFactoryBuilder类的build()方法中再看构造完XMLConfigBuilder类返回Document的下一步: var5 = this.build(parser.parse());
这里看出是解析的方法parse(),具体进到这里面看下XMLConfigBuilder类中的parse()

 public Configuration parse() {
        if(this.parsed) {
            throw new BuilderException("Each MapperConfigParser can only be used once.");
        } else {
            this.parsed = true;
            this.parseConfiguration(this.parser.evalNode("/configuration"));
            return this.configuration;
        }
    }

在这个方法中首先判断了this.parsed真假,其实在这个类的构造方法里已经定义了:
this.parsed = false;所以我们进入到下面的else,这也是防止一个文件只能被解析一次。
看这个方法parser.evalNode(),里面的参数是xml文件的xpath 路径,/configuration,是不是很兴奋,这是配置文件的根节点。进入到方法中,定位到这三个方法

public XNode evalNode(String expression) {
        return this.evalNode(this.document, expression);
    }
public XNode evalNode(Object root, String expression) {
        Node node = (Node)this.evaluate(expression, root, XPathConstants.NODE);
        return node == null?null:new XNode(this, node, this.variables);
    }
private Object evaluate(String expression, Object root, QName returnType) {
        try {
            return this.xpath.evaluate(expression, root, returnType);
        } catch (Exception var5) {
            throw new BuilderException("Error evaluating XPath.  Cause: " + var5, var5);
        }
    }

其实呢很简单就是获得MyBatis配置文件中的configuration节点下的所有内容!依旧返回XNode对象,最后在回到XMLConfigBuilder类中的parse()解析方法中。

目前,从源码清楚地看到通过DOM解析配置文件,最后返回configuration节点下的左右内容的XNode对象后,进行其他的解析。其他部分如何解析,继续下一篇的源码阅读!今儿就到这。

你可能感兴趣的:(MyBatis如何解析mapper.xml中的sql相关信息(一))