深入剖析 MyBatis 核心原理 学习笔记

MyBatis 架构简介

MyBatis分为三层架构,分别是基础支撑层、核心处理层和接口层,如下图所示

MyBatis 三层架构图

基础支撑层

基础支撑层是整个MyBatis框架的地基,为整个MyBatis框架提供了非常基础的功能,其中每个模块都提供了一个内聚的、单一的能力,MyBatis基础支撑层按照这些单一功能可以划分为上图中的九个基础模块。

1、类型转换模块

mybatis-config.xml(MyBatis配置文件)中通过 <typeAliase> 标签为一个类定义一个别名,这里用到的“别名机制”就是由MyBatis基础支撑层中的类型转换模块实现的。

以下是 mybatis-config.xml 配置文件的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!--2333-->
<configuration>

    <properties> <!-- 定义属性值 -->

        <property name="username" value="root"/>

        <property name="id" value="xxx"/>

    </properties>

    <settings><!-- 全局配置信息 -->

        <setting name="cacheEnabled" value="true"/>

    </settings>

    <typeAliases>

        <!-- 配置别名信息,在映射配置文件中可以直接使用Customer这个别名

            代替org.example.domain.Customer这个类 -->

        <typeAlias type="org.example.domain.Customer" alias="Customer"/>

        <typeAlias type="org.example.domain.Address" alias="Address"/>

        <typeAlias type="org.example.domain.Order" alias="Order"/>

        <typeAlias type="org.example.domain.OrderItem" alias="OrderItem"/>

        <typeAlias type="org.example.domain.Product" alias="Product"/>

    </typeAliases>

    <environments default="development">

        <environment id="development">

            <!-- 配置事务管理器的类型 -->

            <transactionManager type="JDBC"/>

            <!-- 配置数据源的类型,以及数据库连接的相关信息 -->

            <dataSource type="POOLED">

                <property name="driver" value="com.mysql.jdbc.Driver"/>

                <property name="url" value="jdbc:mysql://localhost:3306/test"/>

                <property name="username" value="root"/>

                <property name="password" value="xxx"/>

            </dataSource>

        </environment>

    </environments>

    <!-- 配置映射配置文件的位置 -->

    <mappers>

        <mapper resource="mapper/CustomerMapper.xml"/>

        <mapper resource="mapper/AddressMapper.xml"/>

        <mapper resource="mapper/OrderItemMapper.xml"/>

        <mapper resource="mapper/OrderMapper.xml"/>

        <mapper resource="mapper/ProductMapper.xml"/>

    </mappers>

</configuration>

除了“别名转换”机制,类选转换模块还实现了Mybatis中JDBC类型与Java类型之间的相互转换,这一功能在绑定实参、映射ResultSet场景中都有体现:

  • 在sql模板绑定用户传入实参的场景中,类型转换模块会将 Java 类型数据转换成 JDBC 类型数据;
  • 在将 ResultSet 映射成结果对象的时候,类型转换模块会将 JDBC 类型数据转换成 Java 类型数据

具体情况如下图所示:

类型转换基本功能示意图

2、日志模块

日志是我们生产实践中排查问题、定位 Bug、锁定性能瓶颈的主要线索来源,在任何一个成熟系统中都会有级别合理、信息翔实的日志模块,MyBatis 也不例外。MyBatis 提供了日志模块来集成 Java 生态中的第三方日志框架,该模块目前可以集成 Log4j、Log4j2、slf4j 等优秀的日志框架。

3、反射工具模块

Java 中的反射功能非常强大,许多开源框架都会依赖反射实现一些相对灵活的需求,但是大多数 Java 程序员在实际工作中很少会直接使用到反射技术。MyBatis 的反射工具箱是在 Java 反射的基础之上进行的一层封装,为上层使用方提供更加灵活、方便的 API 接口,同时缓存 Java 的原生反射相关的元数据,提升了反射代码执行的效率,优化了反射操作的性能。

4、Binding 模块

可以通过 SqlSession 获取 Mapper 接口的代理,然后通过这个代理执行关联 Mapper.xml 文件中的数据库操作。通过这种方式,可以将一些错误提前到编译期,该功能就是通过 Binding 模块完成的。

这里特别说明的是,在使用 MyBatis 的时候,我们无须编写 Mapper 接口的具体实现,而是利用 Binding 模块自动生成 Mapper 接口的动态代理对象。有些简单的数据操作,我们还可以直接在 Mapper 接口中使用注解完成,连 Mapper.xml 配置文件都无须编写,但如果 ResultSet 映射以及动态 SQL 非常复杂,还是建议在 Mapper.xml 配置文件中维护会比较方便。

5、数据源模块

持久层框架核心组件之一就是数据源,一款性能出众的数据源可以成倍提升系统的性能。MyBatis 自身提供了一套不错的数据源实现,也是 MyBatis 的默认实现。另外,在 Java 生态中,就有很多优异开源的数据源可供选择,MyBatis 的数据源模块中也提供了与第三方数据源集成的相关接口,这也为用户提供了更多的选择空间,提升了数据源切换的灵活性。

6、缓存模块

数据库是实践生成中非常核心的存储,很多业务数据都会落地到数据库,所以数据库性能的优劣直接影响了上层业务系统的优劣。我们很多线上业务都是读多写少的场景,在数据库遇到瓶颈时,缓存是最有效、最常用的手段之一(如下图所示),正确使用缓存可以将一部分数据库请求拦截在缓存这一层,这就能够减少一部分数据库的压力,提高系统性能。

缓存模块结构图

除了使用 Redis、Memcached 等外置的第三方缓存以外,持久化框架一般也会自带内置的缓存,例如,MyBatis 就提供了一级缓存和二级缓存,具体实现位于基础支撑层的缓存模块中。

7、解析器模块

MyBatis 中有两大部分配置文件需要解析,一个是 mybatis-config.xml 配置文件,另一个是 Mapper.xml 配置文件。这两个文件都是由 MyBatis 的解析器模块进行解析的,其中主要是依赖 XPath 实现 XML 配置文件以及各类表达式的高效解析。

8、事务管理模块

持久层框架一般都会提供一套事务管理机制实现数据库的事务控制,MyBatis 对数据库中的事务进行了一层简单的抽象,提供了简单易用的事务接口和实现。一般情况下,Java 项目都会集成 Spring,并由 Spring 框架管理事务。在后面的课程中,我还会深入讲解 MyBatis 与 Spring 集成的原理,其中就包括事务管理相关的集成。