MyBatis 源码分析-项目总览

1.概述

本文主要大致介绍一下MyBatis的项目结构。引用参考资料《MyBatis技术内幕》

此外,https://mybatis.org/mybatis-3/zh/index.html MyBatis官方也提供了很不错的中文文档。对于使用中有碰到一些问题,可以参考一下。

2.模块划分

MyBatis在项目模块划分还是很清晰的。各个模块层次以及具体作用,如下:

模块 层次 定义
session 接口层 提供给外部使用的接口API
scripting 核心处理层 解析映射文件中的动态SQL节点。并形成数据库可执行的SQL语句。
mapping 核心处理层 映射
builder 核心处理层 配置解析
executor 核心处理层 执行器模块,串联整个执行流程。
plugin 核心处理层 插件模块:提供插件接口,通过自定义插件方式对MyBatis进行拓展
cursor 核心处理层 游标模块
reflection 基础支持层 反射模块:mybatis专门对反射模块进行封装。提供更加简单易用的API
type 基础支持层 类型转换模块:Mybatis为简化配置提供了别名机制。提供java类型与JDBC类型转换
logging 基础支持层 日志模块:主要是集成第三方日志
io 基础支持层 资源加载模块:对类加载器进行了封装。确定类加载器顺序,并提供加载文件,以及其他资源的功能
datasource 基础支持层 数据源模块:mybatis自身提供响应的数据源实现,也提供与第三方数据集成的接口。
transaction 基础支持层 事务管理模块:Mybatis 对数据库的事务进行了抽象
parsing 基础支持层 解析器模块:提供两个功能:1. 对XPath进行封装 2为处理动态sql语句中的占位符提供支持
cache 基础支持层 缓存模块:提供一级缓存、二级缓存。优化查询
binding 基础支持层 Binding模块:将自定义的接口与映射配置文件关联起来。通过调用mapper接口完成数据库执行。
exceptions 基础支持层 异常处理
annotations 基础支持层 注解模块
jdbc 其他 JDBC模块
lang 其他 Lang模块

整体结构

整体分为三层:

  • 接口层:定义了MyBatis暴露给应用程序调用的API。
  • 核心处理层:实现了MyBatis的核心处理流程,包括MyBatis初始化以及完成一次数据库操作的涉及的全部流程。
  • 基础支持层:为核心处理层提供了良好的基础支撑。例如:反射、类型转换、日志、缓存、事务等模块。

3.1 基础支持层

3.1.1 反射模块

对应reflection

Java中的反射虽然功能强大,但对大多数开发人员来说,写出高质量的反射代码还是有一定难度的。MyBatis 中专门提供了
反射模块,该模块对Java原生的反射进行了良好的封装,提供了更加简洁易用的API, 方便上层使调用,并且对反射操作进行
了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。

3.1.2 类型转换模块

对应type

正如前面示例所示,MyBatis 为简化配置文件提供了别名机制,该机制是类型转换模块的主要功能之一。 类型转换模块的
另-一个功能是实现JDBC类型与Java类型之间的转换,该功能在为SQL语句绑定实参以及映射查询结果集时都会涉及。在为
SQL语句绑定实参时,会将数据由Java类型转换成JDBC类型;而在映射结果集时,会将数据由JDBC类型转换成Java类型。类
型转换模块的具体原理在第2章详述。

3.1.3 日志模块

对应logging

无论在开发测试环境中,还是在线上生产环境中,日志在整个系统中的地位都是非常重要的。良好的日志功能可以帮助开发人
员和测试人员快速定位Bug代码,也可以帮助运维人员快速定位性能瓶颈等问题。目前的Java世界中存在很多优秀的日志框
架,例如Log4j、Log4j2、 slf4j 等。MyBatis 作为-一个设计优良的框架,除了提供详细的日志输出信息,还要能够集
成多种日志框架,其日志模块的一个主要功能就是集成第三方日志框架。

3.1.4 资源加载模块

对应io

资源加载模块主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能。

3.1.5 解析器模块

对应parsing

解析器模块的主要提供了两个功能:一个功能是对XPath进行封装,为MyBatis初始化时解析mybatis- config.xml配置文
件以及映射配置文件提供支持;另一个功能是为处理动态SQL语句中的占位符提供支持。

3.1.6 数据源模块

对应datasource

数据源是实际开发中常用的组件之一。 现在开源的数据源都提供了比较丰富的功能,例如,连接池功能、检测连接状态等,
选择性能优秀的数据源组件对于提升ORM框架乃至整个应用的性能都是非常重要的。MyBatis 自身提供了相应的数据源实
现,当然MyBatis也提供了与第三方数据源集成的接口,这些功能都位于数据源模块之中。

3.1.7 事务管理

对应transaction

MyBatis对数据库中的事务进行了抽象,其自身提供了相应的事务接口和简单实现。在很多场景中,MyBatis 会与Spring
框架集成,并由Spring框架管理事务

3.1.8 缓存模块

对应cache

在优化系统性能时,优化数据库性能是非常重要的一个环节,而添加缓存则是优化数据库时最有效的手段之一。正确、合理地
使用缓存可以将一部分数据库请求拦截在缓存这一层。MyBatis 中提供了一 级缓存和二级缓存,而这两级缓存都是依赖于基
础支持层中的缓存模块实现的。这里需要读者注意的是,MyBatis中自带的这两级缓存与MyBatis 以及整个应用是运行在同
一个JVM中的,共享同一块堆内存。如果这两级缓存中的数据量较大,则可能影响系统中其他功能的运行,所以当需要缓存大
量数据时,优先考虑使用Redis、Memcache 等缓存产品。

3.1.9 Binding模块

对应binding

通过前面的示例我们知道,在调用SqlSession相应方法执行数据库操作时,需要指定映射文件中定义的SQL节点,如果出现
拼写错误,我们只能在运行时才能发现相应的异常。为了尽早发现这种错误,MyBatis 通过Binding模块将用户自定义的
Mapper接口与映射配置文件关联起来,系统可以通过调用自定义Mapper接口中的方法执行相应的SQL语句完成数据库操作,
从而避免上述问题。值得读者注意的是,开发人员无须编写自定义Mapper接口的实现,MyBatis 会自动为其创建动态代理对
象。在有些场景中,自定义Mapper接口可以完全代替映射配置文件,但有的映射规则和SQL语句的定义还是写在映射配置文件
中比较方便,例如动态SQL语句的定义。

3.1.10 注解模块

对应annotation

随着 Java 注解的慢慢流行,MyBatis 提供了注解的方式,使得我们方便的在 Mapper 接口上编写简单的数据库 SQL 操作代码,而无需像之前一样,必须编写 SQL 在 XML 格式的 Mapper 文件中。虽然说,实际场景下,大家还是喜欢在 XML 格式的 Mapper 文件中编写响应的 SQL 操作。

3.1.11 异常模块

对应 exceptions

定义了 MyBatis 专有的 PersistenceException 和 TooManyResultsException 异常,此外还包ExceptionFactory异常工厂。

3.2 核心处理层

3.2.1 配置解析

对应executor

在MyBatis初始化过程中,会加载mybatis config.xml配置文件、映射配置文件以及Mapper接口中的注解信息,解析后
的配置信息会形成相应的对象并保存到Configuration对象中。例如,示例中定义的<resultMap>节点(即ResultSet的映
射规则)会被解析成ResultMap对象;示例中定义的<result>节点(即属性映射)会被解析成ResultMapping对象。之后,利
用该Configuration对象创建SqlSessionFactory对象。待MyBatis 初始化之后,开发人员可以通过初始化得到
SqlSessionFactory 创建SqlSession对象并完成数据库操作。

3.2.2 SQL解析与Scripting模块

对应executor scripting

拼凑SQL语句是一件烦琐且易出错的过程,为了将开发人员从这项枯燥无趣的工作中解脱出来,MyBatis实现动态SQL语句的
功能,提供了多种动态SQL语句对应的节点,例如,<where>节点、 <if>节点、 <foreach> 节点等。通过这些节点的组合
使用,开发人员可以写出几乎满足所有需求的动态SQL语句。MyBatis中的scripting模块会根据用户传入的实参,解析映射
文件中定义的动态SQL节点,并形成数据库可执行的SQL语句。之后会处理SQL语句中的占位符,绑定用户传入的实参。

3.2.3 SQL执行

对应executor

SQL语句的执行涉及多个组件,其中比较重要的是Executor 、StatementHandler 、ParameterHandler和
ResultSetHandler. Executor 主要负责维护- - 级缓存和二级缓存,并提供事务管理的相关操作,它会将数据库相关
操作委托给StatementHandler完成。StatementHandler首先通过ParameterHandler 完成SQL语句的实参绑定,然后
通过java. sql.Statement对象执行SQL语句并得到结果集,最后通过ResultSetHandler完成结果集的映射,得到结果
对象并返回。

3.2.4 插件

对应plugin

Mybatis 自身的功能虽然强大,但是并不能完美切合所有的应用场景,因此MyBatis提供了插件接口,我们可以通过添加用
户自定义插件的方式对MyBatis进行扩展。用户自定义插件也可以改变Mybatis的默认行为,例如,我们可以拦截SQL语句并
对其进行重写。由于用户自定义插件会影响MyBatis的核心行为,在使用自定义插件之前,开发人员需要了解MyBatis内部的
原理,这样才能编写出安全、高效的插件。

3.3 接口层

对应session

接口层相对简单,其核心是SqlSession 接口,该接口中定义了MyBatis 暴露给应用程序调用的API,也就是上层应用与
MyBatis交互的桥梁。接口层在接收到调用请求时,会调用核心处理层的相应模块来完成具体的数据库操作。

3.4 其他层

3.4.1 JDBC模块

对应 jdbc

JDBC单元测试支持类。【只能说是个测试挂件,白送都不要的那种,随便看看得了 】

3.4.2 Lang模块

里面只包含两个注解【从调用上好像没有任何类用到这个。不知道干啥用的!!原谅我的无知。】

3.5 小结

整体来说,MyBatis的代码结构还是比较简单易懂的。并且分包也比较清晰,见名知意。下面就是MyBatis的整体架构图

MyBatis 源码分析-项目总览的更多相关文章

  1. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

  2. MyBatis 源码分析 - 缓存原理

    1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...

  3. MyBatis 源码分析系列文章导读

    1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...

  4. MyBatis 源码分析

    MyBatis 运行过程 传统的 JDBC 编程查询数据库的代码和过程总结. 加载驱动. 创建连接,Connection 对象. 根据 Connection 创建 Statement 或者 Prepa ...

  5. (一) Mybatis源码分析-解析器模块

    Mybatis源码分析-解析器模块 原创-转载请说明出处 1. 解析器模块的作用 对XPath进行封装,为mybatis-config.xml配置文件以及映射文件提供支持 为处理动态 SQL 语句中的 ...

  6. 精尽 MyBatis 源码分析 - 整体架构

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

  7. 精尽MyBatis源码分析 - MyBatis-Spring 源码分析

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

  8. 精尽MyBatis源码分析 - Spring-Boot-Starter 源码分析

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

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

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

随机推荐

  1. appium自动化的工作原理(1)

    用appium开发移动端自动化测试脚本这么长时间,还没有认证的了解下它的原理是什么,到底是如何实现的呢? 1.先看一个Appium加载的过程图解(来自:了解appium自动化的工作原理--https: ...

  2. VB.Net 正则表达式测试器

    VB.Net制作的正则表达式工具,查询结果可以导出到Excel. 界面截图: 软件下载 Regexp.rar

  3. centos7 ModuleNotFoundError: No module named 'users'

    centos7下运行django项目时ModuleNotFoundError: No module named 'users' 由于我的项目目录是下面这样: 因为找不到users的路径 所以在mana ...

  4. zabbix 使用邮件发送告警信息

    配置系统mail命令,使其可以发送外网邮件 mail 命令配置 修改zabbix_server配置文件,使其可以执行告警脚本 [root@rexen etc]# vim /usr/local/zabb ...

  5. 利用数目找中位数(牛客第七场E)

    https://ac.nowcoder.com/acm/contest/887/E 树状数组做法(代码有注释) #include<bits/stdc++.h> using namespac ...

  6. HDU-6707-Shuffle Card(很数据结构的一道题)

    题目传送门 sol1:拿到这题的时候刚上完课,讲的是指针.所以一下子就联想到了双向链表.链表可以解决卡片移动的问题,但是无法快速定位要移动的卡片,所以再开一个指针数组,结合数组下标访问的特性快速定位到 ...

  7. 蓝桥杯-PREV28-地宫取宝

    先自己用dp解了一遍,然后看了官方讲解视频是用记忆化搜索做的.感觉那位老师的方法比较容易实现(效率上和我的差不多的):记录一下三种方法. 动态规划 地宫取宝 1.195KB C++ 正确 100 15 ...

  8. 【Java集合】试读LinkedList源码

    LinkedList的本质是双向链表.(01) LinkedList继承于AbstractSequentialList,并且实现了Dequeue接口. (02) LinkedList包含两个重要的成员 ...

  9. OpenCV 离散傅立叶变换

    #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include ...

  10. .net批量插入数据库,SqlBulkCopy方法

    /// <summary> /// 把数据插入LessonQuestion表 /// </summary> /// <param name="lessontit ...