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语句执行的完整流程

MyBatis源码分析-MyBatis初始化流程的更多相关文章

  1. 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  2. 精尽 MyBatis 源码分析 - MyBatis 初始化(一)之加载 mybatis-config.xml

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  3. 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  4. 精尽MyBatis源码分析 - MyBatis初始化(四)之 SQL 初始化(下)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  5. 精尽MyBatis源码分析 - MyBatis 的 SQL 执行过程(一)之 Executor

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  6. springboot集成mybatis源码分析-mybatis的mapper执行查询时的流程(三)

    例: package com.example.demo.service; import com.example.demo.dao.UserDao; import com.example.demo.do ...

  7. MyBatis源码分析(各组件关系+底层原理

    MyBatis源码分析MyBatis流程图 下面将结合代码具体分析. MyBatis具体代码分析 SqlSessionFactoryBuilder根据XML文件流,或者Configuration类实例 ...

  8. 精尽MyBatis源码分析 - 文章导读

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

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

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

随机推荐

  1. ASP.NET MVC5+EF6+EasyUI 后台管理系统(60)-系统总结

    系列目录 前言: 起初写这个框架的时候,可以说在当时来说并不是很流行的设计模式,那是在2012年,面向对象的编程大家都很熟悉, 但是“注入.控制反转(DI,IOC,依赖注入).AOP切面编程”新兴名词 ...

  2. 读书笔记--SQL必知必会04--过滤数据

    4.1 使用WHERE子句 在SELECT语句中,数据根据WHERE子句中指定搜索条件进行过滤. 搜索条件(search criteria)也称为(filter condition). WHERE子句 ...

  3. 微服务和SOA服务

    微服务和SOA都被认为是基于服务的架构,这意味着这两种架构模式都非常强调将“服务”作为其架构中的首要组件,用于实现各种功能(包括业务层面和非业务层面).微服务和SOA是两种差异很大的架构模式,但是他们 ...

  4. WCF学习系列汇总

    最近在学习WCF,打算把一整个系列的文章都”写“出来,包括理论和实践,这里的“写”是翻译,是国外的大牛写好的,我只是搬运工外加翻译.翻译的不好,大家请指正,谢谢了.如果觉得不错的话,也可以给我点赞,这 ...

  5. Unicode转义(\uXXXX)的编码和解码

    在涉及Web前端开发时, 有时会遇到\uXXXX格式表示的字符, 其中XXXX是16进制数字的字符串表示形式, 在js中这个叫Unicode转义字符, 和\n \r同属于转义字符. 在其他语言中也有类 ...

  6. [Asp.net 5] Caching-缓存预告

    本节讲Asp.net 5的缓冲.解决方案可以通过网址:https://github.com/aspnet/Caching下载 也是Asp.net 5开源代码介绍的第6部分,前5部分链接如下: 1. D ...

  7. C# - 多线程 之 信号系统

    基础概览 多线程之信号系统命名空间 using System.Threading; 线程同步类的继承层次关系图 终止状态和非终止状态 在终止状态下,被WaitOne()阻塞的线程会逐个得到释放.如果一 ...

  8. bzoj4518--斜率优化DP

    设x[i]为第i天走的路程,s为路程总和,则: ans=[(s/m-x[1])^2+(s/m-x[2])^2+(s/m-x[3])^2+...+(s/m-x[m])^2]*m =[(s-x[1]*m) ...

  9. django入门之模板的用法

    1.为什么要使用模板? 看下以前的代码 #-*- coding:utf-8 -*- from django.shortcuts import render from django.http impor ...

  10. (学习笔记)laravel 中间件

    (学习笔记)laravel 中间件 laravel的请求在进入逻辑处理之前会通过http中间件进行处理. 也就是说http请求的逻辑是这样的: 建立中间件 首先,通过Artisan命令建立一个中间件. ...