在编写mybatis拦截器之前,应该知道mybatis大致的执行流程
- 读取配置(xml),或者是与springboot整合的MybatisAutoConfiguration,都是在进行初始化配置,配置SqlSessionFactory和org.apache.ibatis.session.Configuration
- 执行SQL时创建SqlSession会话,生成执行器(Executor)
- SQL语句处理 StatementHandler
- 参数处理 ParameterHandler
- 结果集处理 ResultSetHandler
大致清楚这几个流程之后就可以编写拦截器插件了,代码
/**
* mybatis的插件,用于记录SQL执行时间,记录的SQL类型包含:query、update
*
* @author lihaoran
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class,
Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
Object.class})
})
public class MybatisSQLExecutionInterceptor implements Interceptor {
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public Object intercept(Invocation invocation) throws Throwable {
Long startTime = System.currentTimeMillis();
try {
return invocation.proceed();
} finally {
Long endTime = System.currentTimeMillis();
Long time = endTime - startTime;
log.debug("SQL执行耗时:{}ms", time);
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
查询拦截了RowBounds.class, ResultHandler.class ,更新没有,因为更新是不需要结果集映射的,只需知道影响的记录数就好。
基础的拦截器已经开发完成,只需让它生效就好。生效的几种方式:
- 在配置文件中(yml.xml)声明,

这种方式我是没找到怎么写,好像是用不了,所以只能选择其他 - 声明bean的方式,其实百度上不少都是@Configuration @Bean的这种方式,可行,但是自己不太想用
- 使用自动配置的方式,就相当于做个自动启动器,只不过这个启动器不需要给外部用,所以也不用在META-INF中新建spring.provides这种方式(类似于spi吧)。
所以选择第三种
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MybatisPluginAutoConfiguration {
@Autowired
public MybatisPluginAutoConfiguration(SqlSessionFactory fac){
org.apache.ibatis.session.Configuration con = fac.getConfiguration();
con.addInterceptor(new MybatisSQLExecutionInterceptor());
}
}
mybatis自动配置类
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
}
}
这里面声明在做一件事 声明SqlSessionFactory ,如果不存在创建它;存在就忽略呗,这也是自己手动配置SqlSessionFactory,自己的可以生效的原因,当然还有个优先级的关系
至此,统计SQL执行耗时的插件已经完成。
通过Configuration con.addInterceptor(new MybatisSQLExecutionInterceptor());点进去这个方法可以看到 将拦截器添加到拦截器链,这样顺序添加的插件应该能顺序执行。(毕竟是个list)
运行截图:

本文介绍如何在MyBatis中实现SQL执行时间的拦截与记录,通过自定义拦截器插件,掌握其核心流程及配置方法,确保SQL执行效率的监控。
1685

被折叠的 条评论
为什么被折叠?



