当前位置: 首页 > news >正文

MyBatis源码分析-MyBatis初始化流程

  MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程。

  MyBatis初始化的过程也就是创建Configuration对象的过程,下面以XML方式为例说明MyBatis是如何完成初始化的(完整测试代码点击MyBatis源码分析-SQL语句执行的完整流程)。

String resouce = "conf.xml";
InputStream is = Resources.getResourceAsStream(resouce);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = sqlSessionFactory.openSession();
user = session.selectOne("com.luoxn28.dao.UserDao.getById", 1);

  以上代码经过了MyBatis初始化、创建SQLSession、执行SQL语句3个过程。根据conf.xml配置文件创建SqlSessionFactory对象,然后创建SqlSession对象,执行SQL语句。其中,MyBatis的初始化就发生在SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is)

       MyBatis初始化基本过程总结如下:SqlSessionFactoryBuilder根据传入的数据流生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例。其中序列图如下:

上图的初始化过程经过以下的几步:

  • 1. 调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
  • 2. SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
  • 3. SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
  • 4. XMLConfigBuilder对象返回Configuration对象;
  • 5. SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
  • 6. SqlSessionFactoryBuilder返回 DefaultSessionFactory对象给Client,供Client使用。

 

SqlSessionFactoryBuilder相关代码:

public SqlSessionFactory build(InputStream inputStream) {
  return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    // 1. 创建XMLConfigBuilder对象解析XML配置
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    // 2. 将XML配置解析成Configuration对象,通过Configuration对象创建SqlSessionFactory
    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.
    }
  }
}
/**
 * 内部通过Configuration对象创建SqlSessionFactory,也可以通过Java API方式创建Configuration对象,
 * 然后调用该方法创建SqlSessionFactory
 */
public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);
}

 

创建Configuration对象过程

  接着上述的 MyBatis初始化基本过程讨论,当SqlSessionFactoryBuilder执行build()方法,调用了XMLConfigBuilder的parse()方法,然后返回了Configuration对象。那么parse()方法是如何处理XML文件,生成Configuration对象的呢?

  1. XMLConfigBuilder会将XML配置文件的信息转换为Document对象,而XML配置定义文件DTD转换成XMLMapperEntityResolver对象,然后将二者封装到XpathParser对象中,XpathParser的作用是提供根据Xpath表达式获取基本的DOM节点Node信息的操作。如下图所示:

  2. 之后XMLConfigBuilder调用parse()方法:会从XPathParser中取出 <configuration>节点对应的Node对象,然后解析此Node节点的子Node:properties, settings, typeAliases,typeHandlers, objectFactory, objectWrapperFactory, plugins, environments,databaseIdProvider, mappers等。

public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return 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);
  }
}

  解析出XML中对应的值后就设置到Configuration对象中,具体解析过程可以阅读对应源代码。Configuration对象创建好之后就会返回,并由此创建DefaultSqlSessionFactory对象。

  mapper.xml文件是在 mapperElement(root.evalNode("mappers")); 中解析的。

 

参考:

1、《深入理解mybatis原理》 Mybatis初始化机制详解

2、MyBatis源码分析-IDEA新建MyBatis源码工程

3、MyBatis源码分析-SQL语句执行的完整流程

 

相关文章:

  • 左神算法进阶班1_4Manacher算法
  • centos下安装mysql5.7
  • [Hadoop in China 2011] 蒋建平:探秘基于Hadoop的华为共有云
  • 系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式
  • PHP删除MySQL数据库下的所有数据表
  • 记:使用Xenocode加壳混淆后,无法“自杀覆盖”的自动更新
  • 数组相关排序
  • 机器学习中的算法(1)-决策树模型组合之随机森林与GBDT
  • Java基础学习总结(23)——GUI编程
  • JDBC 通过PreparedStatement 对数据库进行增删改查
  • JPA常用注解
  • php的插入排序,通过双层for循环
  • 我的Git忽略文件
  • SCSS(SASS、CSS)学习
  • Cenos7下nginx+mysql+php环境的搭建
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • ES6 ...操作符
  • HomeBrew常规使用教程
  • Mac转Windows的拯救指南
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Netty源码解析1-Buffer
  • React as a UI Runtime(五、列表)
  • react 代码优化(一) ——事件处理
  • ucore操作系统实验笔记 - 重新理解中断
  • 闭包,sync使用细节
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 由插件封装引出的一丢丢思考
  • 云大使推广中的常见热门问题
  • 正则表达式小结
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (AngularJS)Angular 控制器之间通信初探
  • (arch)linux 转换文件编码格式
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (二)正点原子I.MX6ULL u-boot移植
  • (四) Graphivz 颜色选择
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .NET 反射 Reflect
  • .NET 设计模式初探
  • .NET4.0并行计算技术基础(1)
  • .NET轻量级ORM组件Dapper葵花宝典
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • :=
  • @requestBody写与不写的情况
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节