676 字
约 2 分钟
6
S08-J02 · 插件与拦截器链
适用读者:想写插件但不知道能拦什么的人。
前置:S08-B01。
覆盖旧文:899(72) + 空壳 1146 补写(E-S08-012)= 72 点。
上一篇:S08-J01 · 分页:PageHelper vs MP 分页插件
下一篇:S08-J03 · 缓存。
1. 一句话结论
MyBatis 插件只能拦四个对象的方法:Executor、StatementHandler、ParameterHandler、ResultSetHandler。拦别的地方不行——这是插件的全部疆域。
| 拦截点 | 能做什么 |
|---|---|
Executor |
改 SQL、加缓存、分页(PageHelper/MP 分页都在这里) |
StatementHandler |
改 PreparedStatement、改 SQL 文本 |
ParameterHandler |
改参数设置(如加密字段) |
ResultSetHandler |
改结果映射(如解密、脱敏) |
2. 插件怎么写
@Intercepts(@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class SqlLogPlugin implements Interceptor {
public Object intercept(Invocation inv) throws Throwable {
Object[] args = inv.getArgs();
MappedStatement ms = (MappedStatement) args[0];
System.out.println("[plugin] " + ms.getId());
return inv.proceed();
}
public Object plugin(Object target) { return Plugin.wrap(target, this); }
}
三个要素:@Intercepts 声明拦哪里、intercept 写逻辑、plugin 用 Plugin.wrap 生成代理。
3. 多个插件的顺序
mybatis-plus:
interceptor-order: ...
或 XML:
<plugins>
<plugin interceptor="...A"/>
<plugin interceptor="...B"/>
</plugins>
顺序规则:按配置顺序包裹(后配置的在外层)。分页插件通常放最后,保证它看到的是最终 SQL。
4. 插件的三个边界
| 边界 | 说明 |
|---|---|
拦不到 SqlSession 的 insert 等高层 API |
那些最终仍走 Executor |
| 拦不到 MyBatis 之外(如 JdbcTemplate) | 插件只作用于 MyBatis |
| 改 SQL 要同步改 count | 否则分页总数不对(J01) |
判据:"我想做的事发生在 SQL 执行前/后吗?" 是 → 插件;不是(如事务、鉴权)→ 拦截器/切面(S07-B03/B04)。
5. 五个误区
| 误区 | 真相 |
|---|---|
| "插件什么都能拦" | 只有四个对象 |
| "插件很多不影响性能" | 每个 SQL 都过一遍代理 |
| "改 SQL 只改 list 就行" | count 也要改 |
| "插件能替代拦截器" | 作用域不同(MyBatis vs MVC) |
| "顺序无所谓" | 顺序影响最终 SQL 形态 |
6. 自检
- 四个拦截点分别能做什么?
- 分页插件拦在哪一层?
- 多个插件的执行顺序规则?
- 插件与 Spring 拦截器的分工?
- 改 SQL 为什么还要管 count?
7. 下一篇
S08-J03 · 缓存:一级/二级与失效
插件讲完,下一篇讲 MyBatis 最容易"看起来生效又好像没生效"的机制:两级缓存。
本篇属于系列《S08 · MyBatis 持久层》。旧文来源:A-899(空壳 1146 补写)。
S08-J02 · 插件与拦截器链
https://www.clxhxhhr.top/posts/5288/ 评论
0 条
还没有评论,先写一条吧。