mybatis插件机制基于jdk动态代理与责任链模式,interceptor为统一入口;通过@intercepts声明拦截点,plugin()包装目标对象,intercept()执行增强逻辑,四大核心对象创建时被逐层代理。

MyBatis 插件机制本质是基于 JDK 动态代理 + 责任链模式,而 Interceptor 接口是整个机制的统一入口和契约规范。它不直接参与代理创建,而是通过约定好的方法签名,让 MyBatis 框架在关键对象(Executor、StatementHandler 等)初始化时自动织入拦截逻辑。
Interceptor 是插件的“行为协议”,不是代理本身
实现 Interceptor 接口只是告诉 MyBatis:“我有增强逻辑”。真正起作用的是框架调用其 plugin(Object target) 方法,把目标对象(比如 StatementHandler 实例)包装成代理对象。这个代理会在方法调用时触发 intercept(Invocation) —— 你写的业务逻辑就在这里执行。
-
intercept()必须重写:所有拦截动作都放这里,比如改 SQL、记日志、统计耗时 -
plugin()一般用默认实现:Plugin.wrap(target, this),它内部用 JDK Proxy 生成代理 -
setProperties()用于接收配置项,比如分页插件读取dialect=MySQL
拦截点由 @Intercepts + @Signature 显式声明
MyBatis 不会盲目拦截所有方法,而是严格按你在类上标注的 @Intercepts 注解来决定哪些对象、哪些方法需要被代理。例如:
-
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})→ 拦截查询执行 -
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})→ 拦截 SQL 准备阶段,适合重写 SQL 实现分页
多个 @Signature 可共存,一个插件能同时处理多个环节,比如既统计耗时又打印带参 SQL。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
四大对象在创建时统一被插件链处理
MyBatis 启动时会构建四类核心对象:Executor、StatementHandler、ParameterHandler、ResultSetHandler。每个对象实例化后,都会经过 InterceptorChain.pluginAll(target) 流程:
- 遍历所有已注册的 Interceptor
- 依次调用它们的
plugin(target)方法 - 返回层层包装后的代理对象(责任链式嵌套)
最终 SqlSession 使用的,已经是被所有插件增强过的对象。执行 SQL 时,调用链会逐层触发各插件的 intercept(),顺序取决于注册顺序。
线程安全与上下文需自行保障
Interceptor 实例是单例的,intercept() 可能被多线程并发调用。因此:
- 避免在插件中使用共享可变状态(如 static 成员变量)
- 若需临时存储上下文(如记录某次查询的开始时间),推荐用
ThreadLocal - 获取当前 SQL、参数、连接等信息,要通过
Invocation的getTarget()和类型判断,再反射或调用对应 getter(如((StatementHandler)target).getBoundSql())
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










