MyBatis 源码学习(一):框架初探

277 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

项目中使用了很久的 MyBatis 框架,终于开始对源码下手了,透过源码不仅可以学习优秀框架中的实现技术,还可以学习大佬们的设计思想,就算仅仅是了解一下源码的实现原理,也会对日常的使用带来极大的好处。

1. 使用 MyBatis

在 MyBatis 官方仓库中可以查看 MyBatis 源码信息,了解项目的结构配置,还可以将源码下载到本地,使用 IDE 打开项目,熟悉 MyBaits 项目的编码风格。

实际使用时,则需要引入 MyBatis 的 Jar 包,或者通过 Maven 工具的 pom.xml 引入依赖信息,使用格式如下,版本信息中填入合适的 MyBatis 版本号信息。

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

2. MyBatis 核心组件

2.1 配置初始化类

  • MyBatis 配置文件

MyBatis 中提供了解析 XML 文件内容来初始化配置信息的功能,配置文件默认名称为:mybatis-config.xml,默认配置在 classpath 路径下。

  • Configuration

Configuration 类是 MyBatis 中的配置类,通过 XMLConfigBuilder 解析器来解析配置文件,并将配置文件内容转换成为 Configuration 配置类对象,即完成了配置文件的加载。

2.2 连接初始化类

  • SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 类作为建造者类,其中的 build() 方法可以用来创建一个 SqlSessionFactory 对象,创建时需要读取配置文件或传入 Configuration 对象作为参数。

  • SqlSessionFactory

SqlSessionFactory 是 MyBatis 中极为重要的工厂接口,想要创建一个 SqlSession 连接,就需要使用 SqlSessionFactory.openSession() 方法创建 SqlSession 对象,实际上 SqlSessionFactory 是一个抽象接口,默认使用其实现类 DefaultSqlSessionFactory 完成连接的初始化创建。

  • SqlSession

SqlSession 则是 MyBatis 必不可少的接口了,通过该接口,可以实现 SQL 语句的执行、事务的管理等。

SqlSession 中定义了基本的 SQL 语句,如 select、update、delete 等,对应的实现类 DefaultSqlSession 中对抽象方法进行了实现。

2.3 SQL 语句执行类

  • Executor

Executor 作为 MyBatis 中的执行器接口,是用来处理 SQL 请求、事务管理、缓存和批处理等操作的,在 SqlSession 连接完成后,执行器会接收到 SQL 请求,然后执行器会根据定义的逻辑来决定如何执行 SQL 语句,并实际通知到 JDBC 处理器开始执行。

Executor有主要的三个实现子类,分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)和BatchExecutor(批处理执行器)。

Executor 在执行具体方法时会根据配置文件创建 StatementHandler 对象,一个 Executor 中可以包含多个 Statement 。

  • StatementHandler

StatementHandler 接口是用来管理和创建 Statement 对象的,通过 prepare() 方法可以创建一个 Statement 对象。

  • Statement

Statement 也是一个基础接口,该类型的对象用来执行静态的 SQL语句,并返回执行结果。该 Statement 对象其实就是 JDBC 中对应的 Statement 对象,对应了 Statement、PreparedStatement、CallableStatement 三种实现。

  • ParameterHandler

ParameterHandler 是 MyBatis 中的参数处理器,用来为 PreparedStatement 中的 SQL 语句参数动态赋值。

在 Executor 执行器方法中创建 StatementHandler 对象后,由 Configuration 创建 ParameterHandler 对象来为 SQL 中的参数绑定具体值。

  • ResultSetHandler

ResultSetHandler 是一个接口,有一个对应的实现类 DefaultResultSetHandler,与 ParameterHandler 参数处理器类似,ResultSetHandler 也是是在处理 SQL 请求的时候由 Configuration 对象创建,对 Statement 执行后的结果集进行处理并得到最终结果列表返回。

3. 作用域和生命周期

对于创建数据库连接的对象,正确的理解其作用域进行使用可以避免一些严重的并发问题,对于 SpringBoot 中使用依赖注入创建时,可以将生命周期的处理全部交由 Spring 容器管理。

3.1 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 的最大特点就是用过即丢,一旦创建 SqlSessionFactory 对象之后,这个类就不需要存在了,因此 SqlSessionFactoryBuilder 的最佳使用范围就是在方法中。

释放 SqlSessionFactoryBuilder 类可以保证解析的 XML 文件资源得以释放,因此 SqlSessionFactoryBuilder 对的生命周期就是当前方法执行过程中。

3.2 SqlSessionFactory

SqlSessionFactory 对象一旦创建就会在整个应用程序运行过程中始终存在,没有理由去销毁或再创建另外一个对象,在应用程序运行中也不建议多次创建 SqlSessionFactory 对象。

因此 SqlSessionFactory 的最佳作用域是应用作用域(Application),即随着应用程序的生命周期一直存在,这种在运行期间有且仅有一个实例的模式就是单例模式。

3.3 SqlSession

SqlSession 对应一次数据库会话,SqlSession 实例不是线程安全的,因此每个线程都应该有自己的 SqlSession 对象实例。

由于数据库会话不是永久的,因此 SqlSession 的生命周期也不是永久的,每次访问数据库时都需要初始化创建新的 SqlSession 对象,在请求执行完成后进行关闭,对应的作用域是请求或方法作用域。

4. MyBatis 核心配置

Executor、StatementHandler、 ParameterHandler 以及 ResultSetHandler 被称为 MyBatis 的四大核心配置。

MyBatis 使用时,由 SqlSessionFactoryBuilder、SqlSessionFactory 和 SqlSession 对象来完成数据库连接的创建,创建完成后就需要该四个核心配置完成后续的 SQL 请求。

4.1 SQL 执行流程

对于一条 SQL 的执行,具体流程简要描述如下:

  1. 首先由 Exector 执行器来进行数据库连接请求并创建 SQL 对应的 StatementHandler 对象,

  2. 然后 StatementHandler 对象会创建得到 Statement 对象,

  3. 之后创建 ParameterHandler 对象并实现对 SQL 中参数进行解析, 语句在数据库中执行,

  4. 最后对于数据库请求返回结果,由 ResultSetHandler 对象完成处理,得到自定义的映射结果。