现象:
自定义插件注册成功,但是始终不进入拦截器方法;
我的拦截器:
排查
Mybatis拦截器是采用的责任链模式,一般拦截器中intercept方法中最后执行 invocation.proceed() 方法,将拦截器责任链向后传递;
但是查看pageHelper源码可以发现,他的拦截器方法中并没有向后传递责任链,而是直接执行了另一个query方法:
- com.github.pagehelper.PageInterceptor#intercept
方案一
不管插件执行顺序,按规范文档来配置自定义插件即可:(即两个query方法都拦截)
方案二
想办法让自定义拦截器,在pageHelper拦截器之前执行,拦截第一个query方法:
(或者配置在pagehelper之后执行,拦截第二个query方法也是可以的);
所以需要使自定义拦截器在pagehelper之后添加;
- 自定义插件配置类上添加注解: @AutoConfigureAfter({PageHelperAutoConfiguration.class})
@Configuration
@ConditionalOnBean({
SqlSessionFactory.class})
@AutoConfigureAfter({
PageHelperAutoConfiguration.class}) // 保证在分页插件之后加载
public class MybatisInterceptorConfig {
…… }
- 将该配置类设置为一个 auto-configuration 类
# 创建src/main/resources/META-INF/spring.factories,声明该配置类即可
# spring.factories文件中 # 自定义配置类的全路径自己修改
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hx.springbootmybatis.order.mybatis.MybatisInterceptorConfig
方案三
就是方案二括号中的方式:(或者配置在pagehelper之后执行,拦截第二个query方法也是可以的); 把方案二中的注解改一下:
@AutoConfigureBefore({
PageHelperAutoConfiguration.class}) // 保证在分页插件之前加载
而且这样还可以捕获到分页语句构建之后的 sql 了!
补充
CachingExecutor中有2个query方法:
另外提一个问题:query方法中调用了同对象中的另一个query方法,会再次进入拦截器吗?
答案:不会;
观察源码得知,mybatis拦截器的执行逻辑是这样的,所以更加肯定的得出结论:不会;
总结:
Mybatis 插件的执行顺序有两种:
1、不同拦截对象执行顺序,如下:
Executor` -> `StatementHandler` -> `ParameterHandler` -> `ResultSetHandler
2、拦截相同对象执行顺序,取决于 mybatis-config.xml 中 <plugin> 配置顺序,越靠后,优先级越高。
3、拦截相同对象执行顺序,如果是使用的配置类加载,则取决于配置类的加载顺序,加载顺序,越靠后,优先级越高;
参考链接:
2、https://zhuanlan.zhihu.com/p/266735787
3、QueryInterceptor 规范