接上篇解析了mybatis核心运行流程的第二阶段-mapper编程模型的构建这块。当时提出的问题在第二阶段其实只解决了一半是吧,那么今天我们就通过核心运行流程的第三阶段--sql数据读写的解析来继续解答这个问题。

核心运行流程

image.png

要把握这个阶段sql数据读写的脉络,在分析源码之前,我们就需要了解整个过程中一个核心的组件:Executor执行组件,它是mybatis数据读写的模板也是基础的设计骨架。

执行组件骨架

image.png

其中Executor:mybatis执行组件的核心接口之一,它定义了数据库操作的基本行为,会话sqlSession所有功能的执行都围绕它来深入和展开;

BaseExecutor: 抽象Executor非缓存这块的行为公共实现和核心接口的算法流程骨架,一些变化的步骤和扩展点(doQuery, doUpdate等实现)都延迟到具体的子执行器实现;

BatchExecutor: sql批处理的子执行器,负责构建和执行sql批处理脚本;

SimpleExecutor: Executor执行器的默认实现,它也是mybatis执行器的默认配置,它使用Preparestatement对象访问数据库;

ReuseExecutor: 在同一会话中根据sql语句对Statement对象进行缓存,默认从缓存中获取数据;

ClosedExecutor: mybatis的预留扩展实现,目前不支持sql的读写操作(未实现);

由以上设计骨架,我们可以看出Executor组件整体的设计是采用了模板方法模式,这种模式核心思想是:

从整体上定义算法的骨架或流程,将部分步骤延迟到子类来实现的思想。模板方法使得子类可以不改变一个算法的结构的同时,可重定义该算法的某些特定实现。在实际项目的组件或框架的开发中,这种模式也用得比较普遍。

image.png

Executor组件源码分析

按照上面的设计,我们来看看这块的源码

image.png

image.png

从上面我们可以明显看出,query内部的实现,明显是在抽象算法的流程和骨架。接着看看之前说的扩展点方法

image.png

看看doQuery, doUpdate在默认配置SimpleExecutor子执行器中的实现

image.png

一、Executor内部调度器

mybatis执行器组件内部实现并不是直接调用的jdbc,而是进行了算法上调度配合 ,主要包含以下核心调度接口

StatementHandler:对Executor的读写数据库的能力进一步抽象,采用策略模式对不同的读写能力进行单独的算法封装;

ParameterHandler:对预编译的SQL进行“?”占位符的替换和赋值,每个参数都对应BoundSql.parameterMappings集合中的一个元素,每个元素对象记录了参数名称、值、类型等相关信息;

ResultSetHandler:对数据库返回的结果集进行封装和POJO的转换等功能;

Executor内部调度对象的运作流程是

image.png

二、调度对象源码分析

先来看在Configuration对象中,集成四大核心处理对象初始化的入口,包括:newExecutor() / newStatementHandler() / newParamenterHandler() / newResultSetHandler() 这几大对象直接决定了Executor内部的执行能力产生。

image.pngimage.png

image.png

image.png

那么写到这里,大家有没有想过这四大核心对象的初始化为什么要在Configuration对象内实现 而不在其它的接口产生?我认为是Configuration作为全局配置目标对象,它拥有四大核心对象创建所需的内部其它协作对象,在这里创建符合设计的思路。

在此方法通过RoutingStatementHandler静态代理,统一把请求路由到其它的StatementHandler接口,默认路由到PrepareStatementHandler对象

image.png

这里以PrepareStatementHandler作为例子,看看query的核心执行代码

image.png

看到这里我们明白,mybatais数据读写能力,最终还是通过jdbc的基础API来实现的。只是mybatis为了设计ORM能力,并让它有更好的维护性、可伸缩性以及性能才这样层层的封装和全局设计。OK文章到这里,还有一个核心的对象未解析:ResultSetHandler对象映射和转换数据。因为这块的细节和内容相对也比较繁杂,不想在这里一笔带过,所以直接放在下次来详细解析。

三、数据读写时序图

最后我们回顾一下之前的源码要点,然后把这个mybatis数据读写的调用时序图绘出来

image.png

总结

今天的mybatis数据读写,Executor执行组件主要源码和业务流程就先分析到这里。源码分析这块不可能把所有相关的源码都晒出来,只能把核心流程的关键点截出来让大家抓住一些重要的点,提供一种看mybatis源码的思路,更多源码还是需要自己去消化,然后变成自己的一些固化的思想。OK, 剩下的内容下次继续分享!更多mybatis的源码干货,请继续关注!