一.插件开发原理
插件是用来改变或者扩展mybatis的原有功能,mybatis的插件就是通过继承Interceptor拦截器实现的,在没有完全理解插件之前禁止使用插件对mybatis进行扩展,否则可能会导致严重问题。
mybatis中能使用插件进行拦截的接口和方法如下:
- Executor(update query flushStatement commit rollback getTransaction close isClose)
- StatementHandler(prepare parameterize batch update query)
- ParameterHandler (getParameterObject setParameters)
- ResultHandler(handlerResults handlerCursorResultSets handleOutputParameters)
插件开发的步骤:
- step1.实现Interceptor接口方法
- step2.确定拦截的签名
- step3.在配置文件中配置插件
- step4.运行测试用例
二.插件开发实例
定义一个阈值,当查询操作运行时间超过这个阈值,记录日志供运维人员定位慢查询。下面是在日志debug模式下,如果不是debug等级下 不需要取Statement代理对象
- step1.实现Interceptor接口方法
@Intercepts({
@Signature(type=StatementHandler.class,method="query",args={Statement.class, ResultHandler.class})
// @Signature(type=StatementHandler.class,method="query",args={MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class})
})
public class ThresholdInterceptor implements Interceptor {
private long threshold;
@Override
public Object intercept(Invocation invocation) throws Throwable {
long begin = System.currentTimeMillis();
Object ret = invocation.proceed();
long end=System.currentTimeMillis();
long runTime = end - begin;
if(runTime>=threshold){
Object[] args = invocation.getArgs();
Statement stat = (Statement) args[0];
MetaObject metaObjectStat = SystemMetaObject.forObject(stat);
PreparedStatementLogger statementLogger = (PreparedStatementLogger)metaObjectStat.getValue("h");
Statement statement = statementLogger.getPreparedStatement();
System.out.println("sql语句:“"+statement.toString()+"”执行时间为:"+runTime+"毫秒,已经超过阈值!");
}
return ret;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
this.threshold = Long.valueOf(properties.getProperty("threshold"));
}
}
特别说明:PreparedStatementLogger实现了InvocationHandler接口,是代理对象中的h,也是让类具有日志打印功能的代理增强类。
PreparedStatementLogger statementLogger = (PreparedStatementLogger)metaObjectStat.getValue("h");
public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
- step2.确定