1. 前言

我们讲解的方式为由浅入深,一定要对框架有一个大概的认识才慢慢去了解其中的具体细节。

本章节讲解的内容主要分为如下四个板块:

  • Mybatis 架构解析
  • Mybatis 生命周期
  • Mybatis 源码分析
  • Mybatis 设计模式

2. Mybatis 架构解析

我们一般把 Mybatis 的功能架构分为三层:

  • API 接口层:提供给外部使用的接口 API,开发人员通过这些本地 API 来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  • 数据处理层:它主要的目的是根据调用的请求完成一次数据库操作,负责具体的 SQL 查找SQL 解析SQL 执行和执行结果映射处理等。
  • 基础支撑层:为上层的数据处理层提供最基础的支撑,负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。

在这里插入图片描述

代码示例

  • 从配置文件(通常是XML文件)得到 SessionFactory ;
  • SessionFactory 得到 SqlSession
  • 通过 SqlSession 进行 CRUD 和事务的操作;
  • 执行完相关操作之后关闭 Session
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void test(){
// 从 XML 中构建 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
// 将XML配置文件构建为Configuration配置
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
// 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactor
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 数据源 执行器 DefaultSqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> employees = mapper.listByEmployee();
employees.forEach(System.out::println);
}
}

3. Mybatis 生命周期

Mybatis 生命周期大概分为如下几步:

  1. Configuration 实例化阶段

    • 当应用启动时,MyBatis 会读取配置文件(如 mybatis-config.xml)并创建一个 Configuration 对象。这个对象包含了 MyBatis 的全局配置信息,包括数据库连接信息、对象映射配置、插件等。
  2. SqlSessionFactory 的创建

    • Configuration 对象被创建后,MyBatis 会基于配置信息构建一个 SqlSessionFactory 对象。SqlSessionFactory 是一个线程安全的工厂类,用于创建 SqlSession 实例。
  3. SqlSession 的生命周期

    • SqlSessionMyBatis 中用于执行 SQL 语句的核心对象。它的生命周期是短暂的,每次需要与数据库进行交互时,都会创建一个新的 SqlSession 对象。在完成操作后,需要显式地关闭 SqlSession,释放相关资源。
  4. Mapper 接口的代理对象

    • MyBatis 中,可以使用 Mapper 接口来定义 SQL 映射操作。MyBatis 会为每个 Mapper 接口创建一个代理对象,该代理对象通过 SqlSession 来执行具体的 SQL 操作。
  5. 执行 SQL 操作

    • 通过 SqlSession 或 Mapper 接口的代理对象,可以执行各种 SQL 操作,包括查询、插入、更新、删除等。
  6. 事务管理

    • 在需要进行事务操作时,可以通过配置来启用 MyBatis 的事务管理。
  7. 插件拦截器

    • MyBatis 允许通过插件来扩展其功能。插件可以拦截 MyBatis 的核心组件,如 ExecutorStatementHandlerParameterHandlerResultSetHandler 等,在其执行过程中添加自定义逻辑。
  8. 资源释放

    • 在应用关闭时,需要显式地关闭 SqlSessionFactory,释放相关的数据库连接和资源,以避免内存泄漏。

MyBatis主要组件生命周期


4. Mybatis 源码分析

我们采用的 Mybatis 3.4.3 进行分析,这样我们就可以在源码的基础上添加注释信息。该部分的源码分析主要是围绕着全局配置文件进行的分析。

参考博文:

mybatis 源码导入IDEA - 未亦末 - 博客园 (cnblogs.com)

https://www.cnblogs.com/RunningSnails/p/17169489.html

4.1. 源码编译

如果需要编译源码需要下载两个部分的源码

  • 将源码下载下来之后将【mybatis-parent-31】进行编译
1
mvn clean install

image-20230825122725045

  • 然后编译【mybatis-3-mybatis-3.5.4
1
2
3
mvn clean

mvn install -Dmaven.test.skip=true

可能会遇到的问题

  1. 由于本人从git 下载的 zip 版本,编译的时候出现如下错误

    1
    failure occured while calling class com.mycila.maven.plugin.license.git.CopyrightRangeProvider
    • 解决方案
    1
    git init
  2. 然后出现如下错误

    1
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-pdf-plugin:1.4:pdf (pdf) on project mybatis: Error during document generation: Error parsing D:\idea-project\mybatis-3.5.3\mybatis-3-mybatis-3.5.4\target\pdf\site.tmp\xdoc\getting-started.xml: Error parsing the model: only whitespace content allowed before start tag and not \ufeff (position: COMMENT seen ...rning permissions and\n       limitations under the License.\n\n-->\n\ufeff... @18:2)
    • 解决方案,将 mybatis-3-mybatis-3.5.4 中的 pom.xml 如下注释
    1
    2
    3
    4
    <!--      <plugin>-->
    <!-- <groupId>org.apache.maven.plugins</groupId>-->
    <!-- <artifactId>maven-pdf-plugin</artifactId>-->
    <!-- </plugin>-->

编译成功

image-20230825135203547

4.2. 引入依赖

我们在《Mybatis-基础知识(一)》基础上进行开发,则需要重新引入本地编译好的 Mybatis 3.5.4 版本

  • 修改 mybatis 3.5.4 的版本号
1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4-xsls</version>
</dependency>
  • 在需要引用的项目中添加引用

image-20230825161438391

  • 如果报错 java.lang.NoClassDefFoundError: ognl/PropertyAccessor , 则添加如下依赖
1
2
3
4
5
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.1.12</version>
</dependency>

4.3. 源码分析

4.3.1. Mybatis 启动流程

  • 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SqlSessionFactory sqlSessionFactory;

@Before
public void init(){
// 从 XML 中构建 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
  • UML 时序图

image-20230907151134759

  • gif 源码追踪

动画