MyBatis插件开发-实现SQL执行耗时监控

MyBatis插件开发实现SQL执行耗时监控

MyBatis插件通过拦截器机制实现SQL执行耗时监控,核心是拦截StatementHandler或Executor相关方法,记录执行前后时间差。

创建自定义拦截器类

自定义拦截器需实现Interceptor接口,添加@Intercepts注解定义拦截目标。以下示例拦截StatementHandler的query和update方法:

java 复制代码
@Intercepts({
    @Signature(type = StatementHandler.class, method = "query", 
        args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", 
        args = {Statement.class})
})
public class SqlCostInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = invocation.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println("SQL执行耗时: " + (endTime - startTime) + "ms");
        return result;
    }
}

注册拦截器到MyBatis配置

在MyBatis配置文件中添加拦截器,或通过编程方式注册:

XML 复制代码
<plugins>
    <plugin interceptor="com.example.SqlCostInterceptor"/>
</plugins>

或通过SqlSessionFactory配置:

java 复制代码
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setPlugins(new SqlCostInterceptor());
    return factory.getObject();
}

增强监控信息输出

可通过MappedStatement获取SQL详细信息,完善监控日志:

java 复制代码
StatementHandler handler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = handler.getBoundSql();
MappedStatement ms = (MappedStatement) 
    ReflectUtil.getFieldValue(handler, "mappedStatement");

String sqlId = ms.getId();
String sql = boundSql.getSql();

使用SLF4J记录日志

推荐整合日志框架替代System.out:

java 复制代码
private static final Logger logger = LoggerFactory.getLogger(SqlCostInterceptor.class);

// 在intercept方法中记录
logger.debug("SQL [{}]执行耗时: {}ms", sqlId, (endTime - startTime));

注意事项

拦截器顺序可能影响执行结果,需通过@Order注解或配置顺序控制。避免在拦截器中执行耗时操作,防止性能影响。生产环境建议添加阈值报警机制,对慢SQL进行标记。

相关推荐
学长毕设3 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
C^h3 小时前
c++ string
开发语言·c++
raindayinrain3 小时前
c++高性能--原子操作,无锁编程,操作顺序
开发语言·c++·性能优化
学逆向的3 小时前
C++ 合并命名空间
开发语言·c++·网络安全
Zhao-Jichao3 小时前
VS2026 打包 C++ 程序生成 EXE,借助 Installer Project 扩展工具
开发语言·c++
zzu123zsw4 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
学逆向的4 小时前
C 局部静态变量
c语言·开发语言·网络安全
大都督会赢的4 小时前
C++第一节课
开发语言·c++
“AI国潮设计-小江”5 小时前
【AIGC实战】Python+Stable Diffusion打造“英歌舞财神”IP,解锁“马到成功”等爆款情绪营销文案设计
开发语言·人工智能·python·prompt·aigc
源码集结号5 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统