Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)

@[TOC] 代理封装阶段—》 门面模式+策略模式
#当前阶段可以说是MyBatis 最神秘的阶段,要理解它,就需要对 Mybatis 的接口层和 binding模块数据源模块进行深入的学习。首先mybatis内部虽然有各种配置文件解析,数据封装,sql执行等复杂的流程,但是基本上都可以通过SqlSession接口进行操作,这种设计就是运用了门面模式;另外mybatis支持通过配置文件灵活配置连接数据库的时候是否使用连接池,这种对操作的封装也是运用了策略模式来实现。下面来详细介绍。

part1:门面模式

	门面模式提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用:

Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第1张图片
优点  
使复杂子系统的接口变的简单可用,减少了客户端对子系统的依赖,达到了解耦的效果;遵循了OO原则中的迪米特法则,对内封装具体细节,对外只暴露必要的接口。
使用场景:
一个复杂的模块或子系统提供一个供外界访问的接口
子系统相对独立 ― 外界对子系统的访问只要黑箱操作即可

part2:话说SqlSession

我们先看一下mybatis的整体架构图:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第2张图片
第二个阶段使用到的第一个对象就是 SqlSession,SqlSession 是 MyBaits 对外提供的最关
键的核心接口,通过它可以执行数据库读写命令、获取映射器、管理事务等;SqlSession 也意味着客户端与数据库的一次连接,客户端对数据库的访问请求都是由SqlSession来处理的,SqlSession 由 SqlSessionFactory 创建,每个 SqlSession 都会引用SqlSessionFactory 中全局唯一单例存在的 configuration 对象。
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第3张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第4张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第5张图片
要 深 入 理 解 SqlSession 就 得 深 入 到 源 码 进 行 学 习 , SqlSession 默 认 实 现 类 为
org.apache.ibatis.session.defaults.DefaultSqlSession
(1) SqlSession 是 MyBatis 的门面,是 MyBatis 对外提供数据访问的主要 API
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第6张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第7张图片
(2) 实际上 Sqlsession 的功能都是基于 Executor 来实现的,遵循了单一职责原则,例如在 SqlSession 中的各种查询形式,最终会把请求转发到 Executor.query 方法,如下图所示:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第8张图片

part3:策略模式

策略模式(Strategy Pattern)策略模式定义了一系列的算法,并将每一个算法封装起来,
而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。Spring 容器中使用配置可以灵活的替换掉接口的实现类就是策略模式最常见的应用。类图如下:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第9张图片
Context:算法调用者,使用 setStrategy 方法灵活的选择策略(strategy);
 Strategy:算法的统一接口;
 ConcreteStrategy:算法的具体实现;
策略模式的使用场景:
(1) 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
(2) 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体
子类时。

part4:SqlSessionFactory设置

SqlSessionFactory 使 用 工 厂 模 式 创 建 SqlSession , 其 默 认 的 实 现 类 为
DefaultSqlSessionFactory , 其 中 获 取 SqlSession 的 核 心 方 法 为
openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean),在这个方法中从 configuration 中获取的 TransactionFactory 是典型的策略模式的应用。运行期,TransactionFactory 接口的实现,是由配置文件配置决定的,可配置选项包括:JDBC、Managed,可根据需求灵活的替换 TransactionFactory 的实现;配置文件截图如下:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第10张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第11张图片

part4:binding 模块

上面提到 SqlSession 是 MyBatis 对外提供数据库访问最主要的 API,但是因为直接使用
SqlSession 进行数据库开发存在代码可读性差、可维护性差的问题,所以我们很少使用,而是使用 Mapper 接口的方式进行数据库的开发。表面上我们在使用 Mapper 接口编程,实际上 MyBatis 的内部,将对 Mapper 接口的调用转发给了 SqlSession,这个请求的转发是建立在配置文件解读、动态代理增强的基础之上实现的,实现的过程有三个关键要素:
 找到 SqlSession 中对应的方法执行;
 找到命名空间和方法名(两维坐标)
 传递参数
要实现上述的步骤,必须对 bindling 模块有深入的分析;
bindling 模块核心类结构如下:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第12张图片
 MapperRegistry:mapper 接口和对应的代理对象工厂的注册中心;
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第13张图片
 MapperProxyFactory:用于生成 mapper 接口动态代理的实例对象;保证 Mapper 实例对象是局部变量;
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第14张图片
 MapperProxy:实现了 InvocationHandler 接口,它是增强 mapper 接口的实现;
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第15张图片
 MapperMethod:封装了 Mapper 接口中对应方法的信息,以及对应的 sql 语句的信息;它是 mapper 接口与映射配置文件中 sql 语句的桥梁; MapperMethod 对象不记录任何状态信息,所以它可以在多个代理对象之间共享;MapperMethod 内几个关键数据结构:
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第16张图片
 SqlCommand : 从 configuration 中获取方法的命名空间.方法名以及 SQL 语句的类
型;
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第17张图片
 MethodSignature:封装 mapper 接口方法的相关信息(入参,返回类型);
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第18张图片
 ParamNameResolver: 解析 mapper 接口方法中的入参,将多个参数转成 Map;
上面介绍了binding的主要对象。现在见到介绍一下binding的大概流程:
首先入口例子:首先是通过sqlSession.getMapper
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第19张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第20张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第21张图片
获取MapperProxyFactory
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第22张图片
通过MapperProxyFactory生成MapperProxy
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第23张图片

通过MapperMethod执行sqlMybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第24张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第25张图片
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第26张图片
这里总结一下时序图:
从 SqlSession.getMapper(Class)方法开始跟踪,画出 binding 模块的时序图如下所示
Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式)_第27张图片
在 binding 模块的运行流程中实现三步翻译的核心方法是MapperMethod.execute(SqlSession,Object[]),翻译的过程描述如下:
 通过 Sql 语句的类型(MapperMethod.SqlCommand.type)和 mapper 接口方法的返
回参数(MapperMethod.MethodSignature.returnType)确定调用 SqlSession 中的某
个方法;
 通过 MapperMethod.SqlCommand.name 生成两维坐标;
 通过 MapperMethod.MethodSignature.paramNameResolve 将传入的多个参数转成
Map 进行参数传递;

前一篇文章介绍了配置文件的加载,这篇文章就是在上一篇文章的基础上,封装代理相关的mapp接口,去执行具体sql,但是最后我们可以看到,sql的具体执行实际上还是转发给sqlSession去处理,sqlSession内部又是通过Executor去和数据库进行交互,所以下一篇文章将继续介绍Executor的执行过程,敬请期待!!!!!

你可能感兴趣的:(Mybatis源码解析(五)-接口绑定阶段(门面模式+策略模式))