MyBatis设计架构

MyBatis 的整体架构分为三层, 分别是基础支持层核心处理层接口层,如下图所示:
MyBatis源码编译与源码详解 - 图1

源码解析

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

构建Configuration类

这里就是读取mybatis-config.xml配置进行解析.
image.png
整个mybatis-config.xml配置包含如下节点的解析
org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
image.png

创建SqlSession对象

这里包含了开启事务,自动提交为false.
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
image.png

综述上边获取session的流程如下所示:
image.png

创建MapperProxy对象

由于mybatis的dao层使用的是接口形式.通过接口是无法调用对应的方法,所以mybatis通过创建MapperProxy代理类来调用对应的接口.
org.apache.ibatis.session.Configuration#getMapper
org.apache.ibatis.binding.MapperRegistry#getMapper
org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
image.png
创建MapperProxy流程如下
image.png

执行mapper方法

当调用mapper方法时,会走到代理类的invoke方法
下面方法org.apache.ibatis.binding.MapperProxy#invoke
image.png
image.png
org.apache.ibatis.binding.MapperProxy.PlainMethodInvoker#invoke
接着执行 MapperMethod.execute(sqlSession, args) 方法。
image.png
进入org.apache.ibatis.binding.MapperMethod#execute()方法后,我们关注查询接口如下:
image.png
org.apache.ibatis.session.defaults.DefaultSqlSession#selectList()
image.png

org.apache.ibatis.executor.statement.PreparedStatementHandler#instantiateStatement
image.png

通过上面的分析,简单总结一下,我们可以抽象出 MyBatis 在执行一条 SQL 查询的过程中涉及到的主要类:Configuration、SqlSession、MapperProxy、Exector,根据这些类画出如下 MyBatis 执行 SQL 的时序图:
image.png

调用Exector实现类实现查询与返回

SqlSession 中的 JDBC 操作部分最终都会委派给 Exector 实现,接着上面的断点往下执行,进入 Exector 的 query 方法。
下面通过时序图描述 Exector 的执行流程,真实的调用链路类比较多,这里简化了调用链路,省略了一些装饰类、代理类,便于理解:
image.png
根据 Exector 执行的时序图,可以抽象出的主要类是:

  1. SqlSession
  2. Exector
  3. StatementHandler
    1. ParameterHandler
    2. ResultSetHandler

StatementHandler 接口是 MyBatis 的核心接口之一,它是 Exector 接口实现的基础。StatementHandler 的主要功能很多,例如创建 Statement 对象,为 SQL 语句绑定实参,执行 SQL 语句,将结果集映射成结果对象。
StatementHandler 类中包含了 ParameterHandler 和 ResultSetHandler 的属性。ParameterHandler 的主要功能是为 SQL 语句绑定实参,也就是使用传入的参数替换 SQL 语句中的“?”占位符。ResultSetHandler 的主要功能是将结果集映射成结果对象。

总体流程可以分如下两张图

获取mapper代理流程
image.png
执行exector
MyBatis源码编译与源码详解 - 图18

总结

总结一下mybatis的原理,简单分如下几步

  1. 读取配置构建Configuration.
  2. 通过配置创建DefaultSqlSessionFactory工厂类
  3. 通过DefaultSqlSessionFactory创建SqlSession
    1. 创建事务工厂
    2. 创建事务管理器
    3. 创建执行器
  4. 通过SqlSession去获取MapperProxy代理类
    1. SqlSession.getMapper()调用configuration.getMapper()调用mapperRegistry.getMapper最后获取MapperProxyFactory
    2. 通过MapperProxyFactory 生成MapperProxy
  5. 通过SqlSession调用Exector创建StatementHandler
  6. 通过StatementHandler调用ParameterHandler 处理参数
  7. 通过prepareStatement执行sql
  8. 通过StatementHandler调用ResultSetHandler 处理返回结果

[参考]:mybatis源码编译
mybatis-3-mybatis-3.5.7.zip
parent-mybatis-parent-32.zip
mck-mybatis-3-mybatis-3.5.7.zip
里面图片有些来自网上copy。