美文网首页解析XML我爱编程
MyBatis如何解析mapper.xml中的sql相关信息(一

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

作者: 萤火之森ss | 来源:发表于2017-08-06 01:34 被阅读24次

    在日常的解析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相关信息(一

        本文链接:https://www.haomeiwen.com/subject/lnfglxtx.html