MyBatis拦截器深度解析与高频面试攻略
🔥 2025年Java面试宝典抢先领:
百度网盘下载链接(持续更新Spring Cloud Alibaba/MyBatis Plus等主流框架剖析)
什么是MyBatis拦截器?
MyBatis拦截器(Interceptor)本质是责任链模式的实现,通过动态代理在SQL执行的生命周期中插入自定义逻辑。举个真实场景:面试官问“如何实现数据分页加密?” 这时拦截器就是标准答案!它能拦截Executor/StatementHandler等四大组件,比如在prepare阶段改写SQL:
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class EncryptInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler handler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = handler.getBoundSql();
String rawSql = boundSql.getSql();
String newSql = encryptField(rawSql); // 字段加密逻辑
reflectSetField(boundSql, "sql", newSql);
return invocation.proceed();
}
}
(注:实际开发需通过反射修改SQL,此处仅示意逻辑)
拦截器核心应用场景
-
SQL性能监控

在query方法前后计算耗时并告警,这对定位慢查询至关重要 -
多租户数据隔离
拦截所有查询语句,自动追加tenant_id=xxx条件 -
敏感数据加解密
如手机号、身份证号在写入前加密,读取时解密 -
分页统一处理
将PageHelper的页码参数动态拼接为limit语句
面试致命陷阱题
问:为什么拦截器对\${}无效?
答:\${}是直接文本替换,而拦截器生效在SQL预编译阶段之后。此时SQL已被解析为BoundSql对象,动态参数已替换完成!正确做法是用#{}配合拦截器修改参数值。
问:多个拦截器执行顺序?
牢记三点:
- 按
@InterceptorOrder值升序执行 - 配置文件中后声明的拦截器先执行
- 嵌套代理结构:
Interceptor3 -> Interceptor2 -> Interceptor1 -> 目标方法
避坑指南
-
线程安全问题
拦截器默认单例,切勿在成员变量存状态数据// 错误示范 ❌ private int queryCount; // 正确做法 ✅ ThreadLocal<Integer> counter = new ThreadLocal<>(); -
慎用反射修改SQL
MyBatis内部类(如BoundSql)字段可能随版本变化,需做兼容性判断 -
拦截器注册方式
Spring Boot中需用@Bean显式声明:@Bean public ConfigurationCustomizer mybatisInterceptor() { return config -> config.addInterceptor(new EncryptInterceptor()); }
💡 面试实战福利:
如果你正在准备技术面试,强烈推荐使用面试鸭会员服务获取最新题库。
👉 通过面试鸭返利网购买会员可享25元返利,大幅降低学习成本!
高频考点思维导图

(涵盖拦截点选择、插件开发流程、Spring集成方案等6大模块)
终极面试策略
当被问到“如何扩展MyBatis功能”时,分三步回答:
1️⃣ 先提基础方案:XML配置/TypeHandler
2️⃣ 强调拦截器的灵活性:列举数据脱敏、SQL审计等场景
3️⃣ 对比优缺点:“拦截器虽强大,但过度使用会破坏框架封装性”
面试官追问:“如果让你设计日志拦截器,怎么避免日志量过大?”
加分回答:
1. 添加`@Logging(ignore = true)`注解跳过特定方法
2. 基于SLF4J的`Logger.isDebugEnabled()`分级输出
3. 对批量操作采用采样日志(每100条记录1次)
掌握这些核心要点,MyBatis拦截器类问题将不再成为你的求职障碍!


