我想为 MyBatis 语句创建一种服务质量,一种全局性能监听器,它将分析所有已执行的 MyBatis 语句并记录那些返回太多命中或花费太长时间的语句。如果可能,尽可能减少对现有业务逻辑的影响。
您可以创建拦截器接口的实现并将其注册为配置文件中的插件。
我只做了一个快速测试,但是像下面这样的自定义拦截器(又名插件)应该可以完成这项工作。
仅当 1) 日志级别为 DEBUG 或更精细且 2) 执行时间超过常量
THRESHOLD_NANOS
的值时才会记录消息。
import java.text.MessageFormat;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
@Intercepts({
@Signature(
type = Executor.class,
method = "update",
args = { MappedStatement.class, Object.class }),
@Signature(
type = Executor.class,
method = "query",
args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class })
})
public class LogExecutionTimeInterceptor implements Interceptor {
private static final Log log = LogFactory.getLog(LogExecutionTimeInterceptor.class);
private static final long THRESHOLD_NANOS = 0L;
@Override
public Object intercept(Invocation invocation) throws Throwable {
long before = System.nanoTime();
Object result = invocation.proceed();
long duration = System.nanoTime() - before;
if (duration > THRESHOLD_NANOS && log.isDebugEnabled()) {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
log.debug(MessageFormat.format(
"Statement {0} took {1} nano seconds", mappedStatement.getId(), duration));
}
return result;
}
}
注册拦截器...
<plugins>
<plugin
interceptor="xxx.yyy.LogExecutionTimeInterceptor" />
</plugins>
@Bean
Interceptor getLogExecutionTimeInterceptor() {
return new LogExecutionTimeInterceptor();
}