Mybatis 插件原理
TIP
MyBatis 允许通过插件在 SQL 执行的关键点进行拦截,实现分页、审计、性能监控等扩展功能。
可拦截的接口
MyBatis 允许拦截以下四个接口的方法:
| 接口 | 方法 | 说明 |
|---|---|---|
| Executor | update, query, flushStatements, commit, rollback | SQL 执行器 |
| StatementHandler | prepare, parameterize, batch, update, query | SQL 语句处理 |
| ParameterHandler | getParameterObject, setParameters | 参数处理 |
| ResultSetHandler | handleResultSets, handleOutputParameters | 结果集处理 |
自定义插件
java
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)
})
public class MyPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置处理
long start = System.currentTimeMillis();
Object result = invocation.proceed(); // 执行目标方法
// 后置处理
long duration = System.currentTimeMillis() - start;
System.out.println("SQL 执行耗时: " + duration + "ms");
return result;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 读取插件配置参数
}
}注册插件
xml
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="com.example.plugin.MyPlugin">
<property name="someProperty" value="value"/>
</plugin>
<!-- 分页插件 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>分页插件示例
java
// 使用 PageHelper 分页(最流行的分页插件)
public PageInfo<User> getUsers(int pageNum, int pageSize) {
// 开启分页(下一行 SQL 会被自动拦截加 LIMIT)
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.selectAll();
return new PageInfo<>(users);
}
// 对应的 XML 无需关心分页
<select id="selectAll" resultType="User">
SELECT * FROM user ORDER BY id DESC
</select>注意事项
java
// 插件执行顺序
// 多个插件会形成链式调用,依次执行
// 可以通过 @Order 或 properties 控制顺序
// 插件不要影响原有的参数和返回值结构
// 注意多数据源场景下的兼容性TIP
插件是 MyBatis 强大的扩展点。PageHelper 分页、通用 Mapper 都是基于插件实现的。