IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> MyBatis源码学习三——StatementHandler与拦截器原理 -> 正文阅读

[游戏开发]MyBatis源码学习三——StatementHandler与拦截器原理

一、StatementHandler

执行器Executer与缓存
上篇讲到一级缓存在BaseExecuter的queryFromDatabase()方法,当没有命中缓存时,从数据库中查询
在这里插入图片描述
doQuery(ms, parameter, rowBounds, resultHandler, boundSql);这个方法在SimpleExecuter中实现
在这里插入图片描述
configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);这里就是创建StatementHandler了,跟进去看
在这里插入图片描述
这个方法第一行创建了一个RoutingStatementHandler。

1.1 RoutingStatementHandler

在这里插入图片描述
RoutingStatementHandler持有一个StatementHandler,这又是一个装饰器模式,它的作用只是为了判断具体使用哪个StatementHandler,默认是PreparedStatementHandler。个人感觉使用RoutingStatementHandler包装一次没啥意义。

1.2 PreparedStatementHandler

回到doQuery()
在这里插入图片描述

  • stmt = prepareStatement(handler, ms.getStatementLog());得到的是一个增加了日志功能的代理PrepareStatement。
  • closeStatement(stmt);在finally中关闭statement,这块和JDBC的写法一样的,只是每一步都有扩展

进入prepareStatement(handler, ms.getStatementLog());在这里插入图片描述

  • Connection connection = getConnection(statementLog);获取一个数据库连接,它最终是从数据源的连接池中产生,关闭也由连接池控制。

二、拦截器

2.1 InterceptorChain

回到doQuery()->configuration.newStatementHandler()方法的第二行
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
这块使用了责任链(所有链都执行,不指定next)+动态代理的模式,把真实的statementHandler 使用拦截器链拦截,然后返回一个statementHandler 的代理类。
在这里插入图片描述
这里我添加了一个分页拦截器也叫分页插件,调用configuration的addInterceptor()方法就可以添加。
在这里插入图片描述
进入interceptor.plugin(target);
在这里插入图片描述
PaginationInterceptor是分页插件,只拦截StatementHandler,因为interceptors里面可以有很多插件,拦截不同的扩展点(Mybatis暴露了4个扩展点)。
进入Plugin.wrap(target, this);
在这里插入图片描述
将目标对象(StatementHandler)和插件(PaginationInterceptor)包装在Plugin(实现InvocationHandler)里面,再返回一个StatementHandler对象的代理。在Plugin中有invoke方法,当执行StatementHandler的方法就会进入invoke中执行,里面会调用PaginationInterceptor的interceptor()方法。
再看第一次循环完之后
在这里插入图片描述
RoutingStatementHandler被代理了,同时和插件绑定在了一起。代理对象target实现了和RoutingStatementHandler一样的接口,如果interceptors还有值,它将再次被代理,和其他插件对象绑定。最后得到的还是一个RoutingStatementHandler的代理对象。

2.2 Intercepts注解

再回到Plugin.wrap(target, this),进入getSignatureMap(interceptor);
在这里插入图片描述
这块是要记录拦截器具体拦截哪些方法,这就需要在拦截器中加上Intercepts注解
在这里插入图片描述
看注解信息,分页拦截器就是拦截的StatementHandler的prepare方法。
再回到prepareStatement(handler, ms.getStatementLog());
在这里插入图片描述
执行RoutingStatementHandler代理类的prepare就进入到了Plugin中的invoke
在这里插入图片描述
先比对是否是被拦截的方法,如果是就执行拦截器的intercept方法

三、PaginationInterceptor

在这里插入图片描述

invocation记录的是被代理的方法,等拦截逻辑执行完还要继续执行原来的方法
在这里插入图片描述
给查询方法加上page参数,就会执行到DialectModel model = DialectFactory.buildPaginationSql(page, buildSql, dbType, dialectClazz);
在这里插入图片描述
跟进去 getDialect(dbType, dialectClazz).buildPaginationSql(buildSql, page.offset(), page.getSize());先得到数据库(MYSQL、ORACLE、DB2…),再进入buildPaginationSql组装分页语句
在这里插入图片描述
然后将带分页的语句设置到BoundSql
在这里插入图片描述
最后执行invocation.proceed();在里面执行被代理类的方法。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:44:40  更:2022-04-01 23:46:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 19:03:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码