了解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、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。

相关推荐
SimonKing3 小时前
Xget:又一下载神器诞生!开源免费无广告,速度拉满!
java·后端·程序员
翟工说3 小时前
Mybatis源码(2)-mapper创建过程
mybatis
冬天vs不冷3 小时前
Java基础(十四):枚举类详解
android·java·python
兜兜风d'3 小时前
jetbrain插件市场无法下载插件/idea插件install无效/idea无法安装插件
java·ide·intellij-idea
minh_coo3 小时前
Spring框架接口之RequestBodyAdvice和ResponseBodyAdvice
java·后端·spring·intellij idea
yeshihouhou3 小时前
tomcat
java·tomcat
Seven973 小时前
Java 日志管理的黄金组合: SLF4J+Logback
java
喵手3 小时前
Java中的大数据流式计算与Apache Kafka集成!
java·华为云·apache
Q_Q5110082853 小时前
python+django/flask哈利波特书影音互动科普网站
spring boot·python·django·flask·node.js·php