Skip to content

Mybatis 插件原理

TIP

MyBatis 允许通过插件在 SQL 执行的关键点进行拦截,实现分页、审计、性能监控等扩展功能。

可拦截的接口

MyBatis 允许拦截以下四个接口的方法:

接口方法说明
Executorupdate, query, flushStatements, commit, rollbackSQL 执行器
StatementHandlerprepare, parameterize, batch, update, querySQL 语句处理
ParameterHandlergetParameterObject, setParameters参数处理
ResultSetHandlerhandleResultSets, 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 都是基于插件实现的。