1. 架构图
2. 基础支撑层
2.1. 类型转换
别名机制 <typeAliase>
2.2. Binding
通过 SqlSession 获取 Mapper 接口的代理,然后通过这个代理执行关联 Mapper.xml 文件中的数据库操作。通过这种方式,可以将一些错误提前到编译期,该功能就是通过 Binding 模块完成的在使用MyBatis 的时候,我们无须编写 Mapper 接口的具体实现,而是利用 Binding模块自动生成Mapper 接口的动态代理对象。有些简单的数据操作,我们还可以直接在Mapper 接口中使用注解完成,连 Mapper.xml 配置文件都无须编写,但如果 ResultSet 映射以及动态 SQL 非常复杂,还是建议在Mapper.xml 配置文件中维护会比较方便。
2.3. 缓存模块
2.4. 解析器模块
一个是 mybatis-config.xml 配置文件,另一个是 Mapper.xml 配置文件。这两个文件都是由 MyBatis的解析器模块进行解析的,其中主要是依赖 XPath 实现 XML 配置文件以及各类表达式的高效解析
3. 核心处理层
MyBatis 核心实现所在,其中涉及 MyBatis 的初始化以及执行一条 SQL 语句的全流程
3.1. 配置解析
mybatis-config.xml配置文件、Mapper.xml 配置文件以及 Mapper 接口中的注解信息。在MyBatis 初始化过程中,会加载这些配置信息,并将解析之后得到的配置对象保存到 Configuration 对象中。
<resultMap> 标签(也就是自定义的查询结果集映射规则)会被解析成ResultMap 对象。我们可以利用得到的Configuration 对象创建 SqlSessionFactory 对象(也就是创建SqlSession 对象的工厂对象),之后即可创建 SqlSession 对象执行数据库操作了。
3.2. SQL 解析与 scripting 模块
MyBatis 的最大亮点应该要数其动态 SQL 功能了,只需要通过MyBatis 提供的标签即可根据实际的运行条件动态生成实际执行的 SQL 语句。MyBatis 提供的动态 SQL 标签非常丰富,包括 <where> 标签、 <if> 标签、 <foreach> 标签、 <set> 标签等。
MyBatis 中的scripting 模块就是负责动态生成 SQL 的核心模块。它会根据运行时用户传入的实参,解析动态SQL 中的标签,并形成 SQL 模板,然后处理 SQL 模板中的占位符,用运行时的实参填充占位符,得到数据库真正可执行的SQL 语句。
3.3. SQL 执行
Executor: 会调用事务管理模块实现事务的相关控制,同时会通过缓存模块管理一级缓存和二级缓存
SQL 语句的真正执行将会由 StatementHandler 实现。
StatementHandler: 会先依赖 ParameterHandler 进行 SQL 模板的实参绑定,然后由 java.sql.Statement 对象将 SQL 语句以及绑定好的实参传到数据库执行,从数据库中拿到 ResultSet,最后,由 ResultSetHandler 将 ResultSet 映射成Java 对象返回给调用方,这就是 SQL 执行模块的核心
4. 插件
很多成熟的开源框架,都会以各种方式提供扩展能力。当框架原生能力不能满足某些场景的时候,就可以针对这些场景实现一些插件来满足需求,这样的框架才能有足够的生命力。这也是MyBatis 插件接口存在的意义。
与此同时,在实际应用的时候,你也可以通过自定义插件来扩展 MyBatis,或者改变 MyBatis 的默认行为。因为插件会影响 MyBatis 内核的行为,所以在自定义插件之前,你必须非常了解 MyBatis 内部的运行 原理,以避免写出不符合预期的插件,引入一些诡异的功能 Bug 或性能问题
5. 接口层
接口层是 MyBatis 暴露给调用的接口集合,这些接口都是使用 MyBatis 时最常用的一些接口,例如, SqlSession 接口、SqlSessionFactory 接口等。其中,最核心的是 SqlSession 接口,你可以通过它实现很 多功能,例如,获取 Mapper 代理、执行 SQL 语句、控制事务开关等。