MyBatis拦截器执行顺序
最近项目用上了mybatis, 但是想像hibernate那样能打印sql, 于是写了个基于mybatis拦截器的sql打印, 参考这个https://blog.22xcode.com/post/78
然后, 碰到了问题, 拦截器会重复输出一句sql
mybatis sql: SELECT id, name FROM usermybatis sql: SELECT id, name FROM user
排查下, 项目里跟mybatis有关的就只有pagehelper了, 猜测可能是pagehelper 为了分页再发了一条算总数count的sql, 而打印sql的拦截器没有获取到count查询的完整sql, 所以看上去发了两遍一样的sql
网上找了下拦截器的资料, 发现基本都是这个样子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Th2xecl-1656070640683)(/storage/thumbnails/_signature/3PUPLE2S14QE5OG0JJL7RED3FL.png)]
大概意思就是后定义/加载的拦截器会先执行.
于是更改配置, 将sql打印拦截器在pagehelper的拦截器之后执行
@Autowiredprivate List<SqlSessionFactory> sqlSessionFactoryList;/*** 在分页拦截器后加载*/@AutowiredPageHelperAutoConfiguration pageHelperAutoConfiguration;@PostConstructpublic void registerInterceptor() {if (enableSqlLog) {MybatisSqlLogInterceptor interceptor = new MybatisSqlLogInterceptor();for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {Configuration configuration = sqlSessionFactory.getConfiguration();if (!containsInterceptor(configuration, interceptor)) {configuration.addInterceptor(interceptor);}}log.warn("[mybatis sql log]已启用, 请检查当前是否为开发环境");} else {log.info("[mybatis sql log]已禁用");}}
其实也试了下
@AutoConfigureAfter
, 但是发现不起作用, 后续再琢磨下吧.
配置完成, 再次执行查询, sql只打印一次, 说明sql打印拦截器在分页拦截器之前被调用, 完成
但是为什么先加载的拦截器反而后执行, 网上好像没啥资料, 那就只能自己翻翻源码了.
debug看了下, 找到了这个类
package org.apache.ibatis.plugin;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class InterceptorChain {private final List<Interceptor> interceptors = new ArrayList<>();public Object pluginAll(Object target) {for (Interceptor interceptor : interceptors) {target = interceptor.plugin(target);}return target;}public void addInterceptor(Interceptor interceptor) {interceptors.add(interceptor);}public List<Interceptor> getInterceptors() {return Collections.unmodifiableList(interceptors);}}
InterceptorChain顾名思义, 拦截链, 可以看到项目定义的拦截器都在InterceptorChain内用ArrayList存储起来
核心是这个InterceptorChain#pluginAll
这个方法
解析下
在pluginAll
方法中, 遍历interceptors
, 为目标对象创建代理.
即, 在这一步, 先加载的拦截器会优先被遍历, 会优先
对目标对象进行代理,
后加载的拦截器, 在原有的代理之上再进行代理, 一层包一层, 类似洋葱.
当方法被调用时, 会先执行最外层的代理方法
.
所以, 先加载到的拦截器, 反而是最后执行
.
MyBatis拦截器执行顺序相关推荐
- 拦截器原理多个拦截器执行顺序
拦截器原理多个拦截器执行顺序 1.根据当前请求,找到**HandlerExecutionChain[可以处理请求的handler以及handler的所有 拦截器] 2.先来顺序执行 所有拦截器的 pr ...
- java 拦截器顺序_Springmvc拦截器执行顺序及各方法作用详解
实现HandlerInterceptor接口或者继承HandlerInterceptor的子类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInt ...
- Mybatis 拦截器执行原理分析
目录 1.拦截器执行流程 2.拦截器实现原理 3.拦截器用法 1.mybatis拦截器实现原理 2.拦截器实现原理 在Mybaits中 拦截器需实现Interceptor接口,加上如下注解 @Inte ...
- 犯罪心理解读Mybatis拦截器
原文链接:"犯罪心理"解读Mybatis拦截器 Mybatis拦截器执行过程解析 文章写过之后,我觉得 "Mybatis 拦截器案件"背后一定还隐藏着某种设计动 ...
- 关于Mybatis拦截器的使用
关于Mybatis拦截器的使用 1 Mybatis拦截器的使用 1 自定义拦截器 1 Interceptor接口 2 @Intercepts注解 3 @Signature注解 2 注册拦截器 3 拦截 ...
- 面试官:你能说说MyBatis拦截器原理吗?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:Format cnblogs.com/fangjian042 ...
- MyBatis拦截器原理探究MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis拦截 ...
- MyBatis拦截器有哪些以及分析
MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允许你在已映射语句执行过程中 ...
- MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...
- insert into select 主键自增_springboot2结合mybatis拦截器实现主键自动生成
点击上方蓝字关注我们 1 01 前言 前阵子和朋友聊天,他说他们项目有个需求,要实现主键自动生成,不想每次新增的时候,都手动设置主键.于是我就问他,那你们数据库表设置主键自动递增不就得了.他的回答是他 ...
最新文章
- 在Yolov5 Yolov4 Yolov3 TensorRT 实现Implementation
- 用FTP客户端实现主机和虚拟机之间文件的传输(方法2)
- mysql 优化 类型_MySQL数据类型的优化选择
- AT91RM9200Linux移植笔记(三)-移植Linux kernel 2.6.17
- 分析工作试用期收获_免费使用零编码技能探索数据分析
- android outofmemory 原理及解决方案
- netlify 部署vue_如何使用Netlify构建和部署网站-全面的教程
- 为什么有的电路中要有两单片机
- shouldoverrideurlloading为什么有时候不走_为什么付出越多,对方就越不懂得感恩,婚姻有时候也需要斤斤计较...
- hibernate could not resolve property
- systen v消息队列(一)
- cad化气路图_气路图符号cad下载
- 抢红包案例分析以及代码实现(一) 侵立删
- oracle 同比增长率计算
- css实现方框内打勾
- 财务管理系统-数据库模块
- 当你对未来迷茫的时候,请打开这个锦囊
- 开心网外挂开发之 三
- php实现拼音转中文,PHP将中文转换成拼音的方法
- 如何发布自己的npm包(超详细步骤,博主都在用)