了解Mybatis拦截器

摘要

本文介绍了MyBatis拦截器的作用机制、注意事项、拦截顺序以及四类拦截点的应用场景和用法。

认识MyBatis拦截器

MyBatis拦截器是MyBatis提供的一种扩展机制,基于Java动态代理和反射机制实现,允许开发者在SQL执行过程中的关键节点插入自定义逻辑。

生命周期

Interceptor接口的三个方法。intercept实现所有拦截逻辑,plugin通过Plugin.wrap(target,this)为目标对象创建代理,setProperties用于读取配置中的属性值。

步骤实现

1.拦截器注册:通过@Intercepts注解指定拦截点。

2.代理对象生成:MyBatis使用Plugin类为目标对象(如Executor)创建代理。

3.方法拦截:当调用目标方法时,代理会触发拦截器的intercept方法。

4.逻辑执行:在intercept中可修改参数、执行原方法、处理返回值。

拦截顺序

StatementHandler.prepare

→ParameterHandler.setParameters

→Executor.update/query

→ResultSetHandler.handleResultSets

注意事项

  • 性能影响:拦截器会增加SQL执行的额外开销,避免在高频操作中使用复杂逻辑。
  • 线程安全:使用ThreadLocal存储搜索参数,确保线程隔离。
  • 参数绑定:动态生成的参数需要与ParameterMapping对应,避免参数丢失。
  • SQL注入:参数使用?占位符绑定,确保安全。
  • 避免过度拦截:不同的拦截点可能会重复拦截同一个 SQL 操作,需注意逻辑冲突。

可选拦截点应用场景

  • 数据脱敏:ResultSetHandler拦截,在结果集中对敏感字段如手机号、身份证号进行脱敏处理。
  • 自动分页:StatementHandler拦截,自动拼接分页SQL。
  • 参数预处理:ParameterHandler拦截,对入参进行加密、格式校验或默认值填充。
  • 日志监控:Executor拦截,统计SQL执行时间,识别慢查询。

四大类

在MyBatis中,使用@Intercepts注解定义拦截器时,需要通过@Signature指定拦截的目标接口、方法和参数,分为四大类:

StatementHandler部分

less 复制代码
//用于拦截 SQL 语句的准备阶段
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class })
})
public class PrepareInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截参数绑定阶段
@Intercepts({
        @Signature(type = StatementHandler.class, method = "parameterize", args = { Statement.class })
})
public class ParameterizeInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截 INSERT、UPDATE、DELETE 的执行阶段
@Intercepts({
        @Signature(type = StatementHandler.class, method = "update", args = { Statement.class })
})
public class UpdateStatementInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截 SELECT 查询的执行阶段。
@Intercepts({
        @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class })
})
public class QueryStatementInterceptor implements Interceptor { // 实现 intercept 方法 }

ParameterHandler部分

less 复制代码
//用于拦截参数绑定到 PreparedStatement 的阶段
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = { PreparedStatement.class })
})
public class ParameterInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截获取参数对象的阶段
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "getParameterObject", args = {})
})
public class GetParameterInterceptor implements Interceptor { // 实现 intercept 方法 }

Executor部分

less 复制代码
//用于拦截 INSERT、UPDATE、DELETE 操作
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class UpdateInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截 SELECT 查询。
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })
})
public class QueryInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截事务提交操作
@Intercepts({
        @Signature(type = Executor.class, method = "commit", args = { boolean.class })
})
public class CommitInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截事务回滚操作
@Intercepts({
        @Signature(type = Executor.class, method = "rollback", args = { boolean.class })
})
public class RollbackInterceptor implements Interceptor { // 实现 intercept 方法 }

//同时拦截 Executor.update 和 StatementHandler.prepare
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }),
        @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class })
})
public class MyInterceptor implements Interceptor { // 实现 intercept 方法 }

ResultSetHandler部分

less 复制代码
//用于拦截结果集的处理阶段
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class })
})
public class ResultHandlerInterceptor implements Interceptor { // 实现 intercept 方法 }

//用于拦截存储过程输出参数的处理阶段
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleOutputParameters", args = { CallableStatement.class })
})
public class OutputParameterInterceptor implements Interceptor { // 实现 intercept 方法 }

总结

以上我们了解了MyBatis拦截器的作用机制、注意事项及拦截顺序,四类拦截点,当我们使用注解自定义拦截器时,需要遵循特定组合写法,并实现方法细节。

关注公众号:咖啡Beans

在这里,我们专注于软件技术的交流与成长,分享开发心得与笔记,涵盖编程、AI、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。

相关推荐
孤廖24 分钟前
吃透 C++ 栈和队列:stack/queue/priority_queue 用法 + 模拟 + STL 标准实现对比
java·开发语言·数据结构·c++·人工智能·深度学习·算法
我命由我1234526 分钟前
Android 对话框 - 对话框全屏显示(设置 Window 属性、使用自定义样式、继承 DialogFragment 实现、继承 Dialog 实现)
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Full Stack Developme36 分钟前
java.net 包详解
java·python·.net
一叶飘零_sweeeet1 小时前
深入 Spring 内核:解密 15 种设计模式的实战应用与底层实现
java·spring·设计模式
凤山老林1 小时前
排序算法:详解插入排序
java·开发语言·后端·算法·排序算法
彦楠1 小时前
IDEA实用快捷键
java·ide·intellij-idea
豆沙沙包?1 小时前
2025年--Lc197-077. 排序链表(链表,尾插法)--Java版
java·数据结构·链表
m0_651593911 小时前
深入理解软件设计中的协议与规范:从理论到Java实践
java·软件工程·代码规范·设计规范
低音钢琴1 小时前
【SpringBoot从初学者到专家的成长18】SpringBoot中的数据持久化:JPA与Hibernate的结合
spring boot·后端·hibernate
paopaokaka_luck1 小时前
基于SpringBoot+Vue的社区诊所管理系统(AI问答、webSocket实时聊天、Echarts图形化分析)
vue.js·人工智能·spring boot·后端·websocket