MyBatis插件中@Intercepts和@Signature注解用于精准拦截四大核心对象(Executor、ParameterHandler、StatementHandler、ResultSetHandler)的指定方法,必须严格匹配type、method、args三要素;@Intercepts为类级注解,声明拦截器身份并接受一个或多个@Signature数组;@Signature通过type定位接口、method指定方法名、args按顺序完整声明参数类型以区分重载,二者配合Interceptor接口实现方法增强。

MyBatis 插件中 `@Intercepts` 和 `@Signature` 是声明拦截器的核心注解,配合 `Interceptor` 接口使用,用于精准定位要增强的方法。关键不是“加了注解就生效”,而是类型、方法名、参数列表三者必须严格匹配 MyBatis 四大核心对象的实际签名。
@Intercepts:声明这是一个拦截器类
它是一个**类级别注解**,只能加在实现了 `Interceptor` 接口的类上。它的作用是告诉 MyBatis:“这个类要参与插件链,别跳过”。
- 必须传入一个 `@Signature` 数组(哪怕只拦截一个方法,也要用 `{@Signature(...)}` 包裹)
- 不支持嵌套或继承;一个类只能有一个 `@Intercepts`
- 若配置多个 `@Signature`,表示该拦截器同时作用于多个目标方法(共用同一套 `intercept()` 逻辑)
@Signature:精确指定拦截点
它定义“拦谁、拦哪个方法、拦哪一重载”,三个属性缺一不可:
-
type:四大对象之一 ——
Executor、ParameterHandler、StatementHandler或ResultSetHandler -
method:该对象接口中声明的公开方法名(如
prepare、query、handleResultSets),注意大小写和拼写 - args:对应方法的**完整参数类型数组**,用于区分重载。必须和源码中该方法的 `public xxx method(xxx a, xxx b)` 参数类型、顺序完全一致(例如 `MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class`)
常见错误:把 `args` 写成 `String.class`(实际是 `Object.class`),或漏掉泛型擦除后的原始类型(如 `List.class` 错,应为 `java.util.List.class` 或更准确的 `java.util.ArrayList.class` —— 但通常用接口类型即可)。
立即学习“Java免费学习笔记(深入)”;
典型配置示例
下面是一个同时拦截 SQL 准备和结果处理的写法:
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class SqlAuditInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 根据 invocation.getTarget().getClass() 和 invocation.getMethod().getName()
// 可判断当前实际进入的是 prepare 还是 handleResultSets
System.out.println("正在拦截: " + invocation.getMethod().getName());
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
注意:两个 `@Signature` 共享同一个 `intercept()` 方法,内部需自行判断上下文;若逻辑差异大,建议拆分成两个独立拦截器类。
配置生效的必要条件
- 拦截器类必须被 MyBatis 加载:通过 `
` 标签注册到 `mybatis-config.xml`,或在 Spring 中调用 `configuration.addInterceptor(...)` - `plugin()` 方法不能被重写为直接返回 `target`(否则代理失效)
- 确保 `args` 类型与 MyBatis 版本源码一致(不同版本方法签名可能微调,比如 `Integer` vs `int`、新增参数等)


















