文档章节

mybatis源码分析之Configuration

u
 udbwcso
发布于 2016/04/18 11:58
字数 823
阅读 3407
收藏 89

上一篇mybatis之SqlSessionFactory

http://my.oschina.net/u/657390/blog/653637

上一篇对mybatis中SqlSessionFactory的创建过程进行了分析,从之前的分析可以看出创建过程中比较重要的一部分是Configuration,这一篇将重点分析配置文件的读取.

以官方的例子来进行分析.

mybatis-config.xml是mybatis最开始的地方,dataSource,mappers等的配置都在这里.

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

进入SqlSessionFactoryBuilder,可以看出最终所有的build方法都是调用的以下方法:

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.
    }
  }
}

environment:环境,MyBatis 可以配置成适应多种环境,例如开发,测试和生产.

XMLConfigBuilder与Configuration之间的关系

从这张图可以看出使用了建造者模式.

在build方法里涉及到与读取配置相关的代码

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//构造方法
//XMLMapperEntityResolver离线MyBatis dtd实体解析器
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
  this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

比较重要的部分是创建XPathParser实例

new XPathParser(inputStream, true, props, new XMLMapperEntityResolver())
//创建XPathParser实例
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
  commonConstructor(validation, variables, entityResolver);
  this.document = createDocument(new InputSource(inputStream));
}

commonConstructor完成的工作如下

private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
  this.validation = validation;
  this.entityResolver = entityResolver;
  this.variables = variables;
  //使用默认的对象模型得到一个新的XPathFactory实例
  XPathFactory factory = XPathFactory.newInstance();
  this.xpath = factory.newXPath();
}

XPathFactory,XPath,XPathFactoryImpl,XPath之间的关系

可以看出使用了工厂方法模式.

接着就是调用createDocument创建document的过程

XMLConfigBuilder创建后调用parse()

parser.parse()
//parse()源码
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")获取到的是根结点

    /**
     * 读取配置文件组装configuration
     * @param root 配置文件的configuration节点
     */
  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

从上面的代码可以比较清晰的看出在读取配置文件的过程比较重要的类有:XNode,XPathParser

XNode是Node类的扩展,XPathParser是xml文件的解析器工具类.

XPathParser中比较重要的方法是:public XNode evalNode(String expression)

evalNode最终调用的是com.sun.org.apache.xpath.internal.jaxp.XPathImpl里的

public Object evaluate(String expression, Object item, QName returnType)

XPath的相关资料:

http://www.w3school.com.cn/xpath/index.asp

例子

import org.apache.ibatis.io.Resources;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

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

public class XPathExample {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        String resource = "com/analyze/mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        Document doc = builder.parse(inputStream);

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        XPathExpression expr
                = xpath.compile("/configuration/mappers/mapper");
        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;
        for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println(nodes.item(i).getAttributes().getNamedItem("resource").getNodeValue());
        }

    }
}

xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <configuration>
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
  </configuration>

 

© 著作权归作者所有

u
粉丝 86
博文 66
码字总数 15709
作品 0
武汉
私信 提问
加载中

评论(6)

u
udbwcso 博主

引用来自“开源中国全球总代理”的评论

恳请发我个yFiles UML wowxndnaken@126.com,多谢了
用的是IntelliJ IDEA
开源中国全球总代理
开源中国全球总代理
恳请发我个yFiles UML wowxndnaken@126.com,多谢了
中小宇
中小宇
学习
三国
4
三国
weqwewqeqwesadasd
三国
12345qweqweqwqwe
mybatis源码分析之TypeHandler

上一篇: mybatis源码分析之MapperMethod https://my.oschina.net/u/657390/blog/755787 分析了MapperMethod从创建到执行的过程,MapperMethod的执行包括执行sql返回结果. 在执行sql和返回结果...

udbwcso
2016/11/18
314
0
mybatis源码分析之SqlSession的创建过程

mybatis之SqlSessionFactory mybatis源码分析之Configuration mybatis源码分析之事务管理器 以上是之前的分析,在mybatis源码分析之事务管理器里分析到了事务管理器 SqlSession session = s...

udbwcso
2016/04/21
1K
0
mybatis(三)配置详解之properties与environments

上一篇我们通过对mybatis源码的简单分析,可看出,在mybatis配置文件中,在configuration根节点下面,可配置properties、typeAliases、plugins、objectFactory、objectWrapperFactory、setti...

LCZ777
2014/12/18
0
0
mybatis之SqlSessionFactory

版本:mybatis-3 主要分析SqlSessionFactory的构建过程 SqlSessionFactoryBuilder从XML中构建SqlSessionFactory SqlSessionFactoryBuilder用来创建SqlSessionFactory实例,一旦创建了SqlSessio......

udbwcso
2016/04/06
710
0
mybatis-sql执行流程源码分析

SqlSessionFactory 与 SqlSession.   通过前面的章节对于mybatis 的介绍及使用,大家都能体会到SqlSession的重要性了吧, 没错,从表面上来看,咱们都是通过SqlSession去执行sql语句(注意...

architect刘源源
06/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊spring cloud的ConsulServiceRegistry

序 本文主要研究一下spring cloud的ConsulServiceRegistry ServiceRegistry spring-cloud-commons-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/client/serviceregistry/ServiceR......

go4it
12分钟前
0
0
Nextjs 学习 —— hooks

22

lemos
21分钟前
0
0
如何在spring mvc restful接口中定制化类型转换和格式化

1.痛点 最近小胖哥搞了个小程序,有几个spring mvc 接口传递了时间,时间用java 8 time 相关的api 来直接接收: 当使用根据ISO 8601格式化的参数向任何这些方法发送POST请求时,报出了如下异...

码农小胖哥
36分钟前
2
0
docker日志监控

日志处理机制 我们先来了解一下docker日志处理的机制,当启动一个容器的时候,它其实是docker daemon的一个子进程,docker daemon可以拿到你容器里面进程的标准输出,拿到标准输出后,它会通...

爱宝贝丶
36分钟前
2
0
域名已备案,但jsapi添加支付授权目录依然提示支付授权目录未通过ICP备案!!!

问题描述: 一网站域名xxx.cn已备案成功,在全国工业和信息化部(http://beian.miit.gov.cn/publish/query/indexFirst.action)查询到备案成功的,但是在微信商户平台配置jsapi添加支付授权目录...

闊苡訆涐囍醣
41分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部