总文档 :文章目录
Github : github.com/black-ant
一 . 前言
文章目的 :
- 了解 MyBatis 插件的用法
- 了解 主要的源码逻辑
- 了解 PageHelper 的相关源码
这是一篇概括性文档 , 用于后续快速使用相关功能 , 整体难度较低.
二 . 流程
2.1 基础用法
基础拦截器类
1 | java复制代码@Intercepts( |
基础配置类
1 | java复制代码@Configuration |
这里可以看到 , 拦截到的参数如下 :
2.2 功能详解
整个拦截过程有几个主要的组成部分 :
Interceptor 拦截器接口
1 | java复制代码 |
InterceptorChain 拦截器链
InterceptorChain 是一个拦截器链 , 用于执行相关的Interceptor 操作 , 其中有一个拦截器集合
1 | java复制代码// 主要的大纲如此所示 |
注解 @Intercepts 和 @Signature
这是过程中主要涉及的2个注解 :
- @Intercepts : 定义拦截器 , Intercepts 中可以包含一个 Signature 数组
- @Signature : 定义类型
- type : 拦截器处理的类
- method : 拦截的方法
- args : 方法参数 (重载的原因)
2.3 源码跟踪
Step 1 : 资源的加载
资源的加载主要是对对应方法的代理逻辑 , 从前文我们可以看到 , 一个 plugin 操作 , 主要包含2个步骤 :
1 | java复制代码 |
来跟进一下相关的操作 :
1 | java复制代码C01- Configuration |
Step 2 : plugin 的构建
Step 1 中已经完成了相关 interceptors 的添加 , 这个环节需要通过 Interceptor 构建对应的 Plugin
先来看一下调用链 :
- C- SqlSessionTemplate # selectList : 发起 Select 请求
- C- SqlSessionInterceptor # invoke : 构建一个 Session 代理
- C- SqlSessionUtils # getSqlSession : 获取 Session 对象
- C- DefaultSqlSessionFactory # openSessionFromDataSource
- C- Configuration # newExecutor
整体来说 ,从 getSqlSession 开始关注即可
1 | java复制代码 |
DefaultSqlSessionFactory 构建一个 Session , 同时调用 Plugin 生成逻辑
此处构建 Session 的同时 , 最终调用 Plugin warp 构建 Plugin
1 | java复制代码C- DefaultSqlSessionFactory |
Step 3 : invoke 执行
拦截器的实现是基于 Proxy 代理实现的 , 在上文看到了代理的生成 , 这里看一下代理的调用 :
以 Query 为例 :
当调用 Executor 中 Query 方法时 , 会默认调用代理类 , 上文说了 Execute 的构建 , 那么他在整个逻辑中是作为什么角色的?
Executor 作用 : Executor 是 Mybatis 中的顶层接口 , 定义了主要的数据库操作方法
1 | java复制代码public interface Executor { |
execute 的调用 :
前面构建 Session 的时候 , 已经为其定义了Plugin , 以下为 Plugin 的主要流程
1 | java复制代码// 1 . 选择合适的 plugin |
三 . 扩展 PageHelper
以下为 PageHelper 中如何使用相关的拦截器方法的 :
PageHelper 中主要有 2个拦截器 :
- QueryInterceptor : 查询操作插件
- PageInterceptor : 分页操作插件
主要看一下 PageInterceptor 拦截器 :
拦截器代码
1 | java复制代码@Intercepts( |
补充 :ExecutorUtil.executeAutoCount 相关逻辑
1 | java复制代码/** |
补充 : pageQuery 查询
1 | java复制代码public static <E> List<E> pageQuery(Dialect dialect, Executor executor, MappedStatement ms, Object parameter, |
因为源码的注释程度很高 , 所以基本上不需要做额外的标注了 , 整体的流程就是 :
- Step 1 : 拦截器 intercept方法定义整体逻辑
- Step 2 : count 方法决定他是否分页
- Step 3 :pageQuery 调用方言进行事情SQL的拼接
整体中有几点值得关注 :
- 只生成分页的 row 和 pageKey 等 , 在最终通过方言组合 , 以适应多种数据库结构
- 核心还是调用 executor.query 原生方法
简述一下 PageHepler 的绑定流程
核心处理类为 AbstractHelperDialect , 先从创建开始 :
1 | java复制代码PageHelper.startPage(page, size); |
剩下逻辑也比较清晰 , 也不涉及太多此处逻辑了 , 有需求再看更多
总结
这应该是写的最简单的一篇源码分析了 , 除了本身结构不复杂以外 , 相关源码的注释也很清晰 , 基本上没有什么分析的需求.
拦截器的使用 :
- 准备拦截器类
- sqlSessionFactory.getConfiguration().addInterceptor(interceptor) 添加拦截器
PageHelper 核心 :
- parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey) : 获取分页的参数
- dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey) : 参数解析为 SQL
- ThreadLocal 保存参数
后续我们再关注一下Mybatis 其他要点和 PageHelper 的整体涉及优势
本文转载自: 掘金