插件概述:

插件是用来改变或者扩展mybatis的原有功能,mybatis的插件就是通过继承Interceptor拦截器实现的,在没有完全理解插件之前j禁止使用插件对mybatis进行扩展,有可能会导致严重的问题;

mybatis中能使用插件进行拦截的接口和方法如下:

Executor(update,query,flushStatement,commit,rollback,getTransation,close,isClose);

StatementHandler(prepare,parameterize,batch,update,query);

ParameterHandler(getParameterObject,setParameters);

ResultSetHandler(handleResultSets.handleCursorResultSets,handleOutputParameters);

插件实现步骤:

1:实现Interceptor接口方法

2:确定拦截的签名

3:在配置文件中配置插件

4:运行测试用例

本来不打算写的,后来想想写一个吧;

先看一下接口;

 /**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.plugin; import java.util.Properties; /**
* @author Clinton Begin
*/
public interface Interceptor { /**
* 执行拦截逻辑的方法
* @param invocation
* @return
* @throws Throwable
*/
Object intercept(Invocation invocation) throws Throwable; /**
*
* @param target 被拦截的对象,他的作用就是给拦截的对象生成一个代理对象
* @return
*/
default Object plugin(Object target) {
return Plugin.wrap(target, this);
} /**
* 读取 在plugin中设置的参数
* @param properties
*/
default void setProperties(Properties properties) {
// NOP
} }

手写慢SQL插件拦截器

 package org.apache.ibatis.plugin.impl;

 import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.jdbc.PreparedStatementLogger;
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.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler; import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties; /**
* @Description 慢SQL查询日志拦截器
* @ClassName ThresholdInterceptor
* @Author mr.zhang
* @Date 2020/3/23 21:35
* @Version 1.0.0
**/ /**
* 定义拦截位置
* 参数解释:
* type:拦截的类
* method:该类的那个方法
* args:该方法的参数
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "query", args = {Statement.class,ResultHandler.class})
})
public class ThresholdInterceptor implements Interceptor { // 时间阈值
private Long threshold; @Override
public Object intercept(Invocation invocation) throws Throwable {
long begin = System.currentTimeMillis();
Object proceed = invocation.proceed();
long end = System.currentTimeMillis();
long runTime = end - begin;
// 如果大于等于阈值那么记录慢SQL
if(runTime>=threshold){
// 获取参数
Object[] args = invocation.getArgs();
// 根据方法参数可得知第0个是Statement
Statement stmt = (Statement) args[0];
// 通过反射转化为metaObject
MetaObject metaObject = SystemMetaObject.forObject(stmt);
// getValue("h")是因为在动态代理中存在的InvocationHandler就是h
// protected InvocationHandler h; 在Proxy类中定义的 在动态代理生成代理类时都会存在
PreparedStatementLogger preparedStatementLogger = (PreparedStatementLogger) metaObject.getValue("h");
PreparedStatement preparedStatement = preparedStatementLogger.getPreparedStatement();
System.out.println("Sql语句:“"+preparedStatement.toString()+"”执行时间为:"+runTime+"毫秒,已经超过阈值!");
} return proceed;
} @Override
public void setProperties(Properties properties) {
this.threshold = Long.valueOf(properties.getProperty("threshold"));
}
}

如果需要使用在mybatis-config.xml 的plugins中配置就可以了,记得配置阈值哦;

作者:彼岸舞

时间:2020\03\23

内容关于:Mybatis

本文部分来源于网络,只做技术分享,一概不负任何责任

Mybatis源码学习第七天(插件开发原理)的更多相关文章

  1. Mybatis源码学习第七天(PageHelper分析)

    其实我本来是不打算写这个PageHelper的,但是后来想了想,还是写了吧!现在市场用Mybatis的产品分页应该差不多都是用PageHelper来实现的,毕竟Mybatis的分页rowbound.. ...

  2. Mybatis源码学习第七天(插件源码分析)

    为了不把开发和源码分析混淆,决定分开写; 接下来分析一下插件的源码,说道这里老套路先说一个设计模式,他就是责任链模式 责任链模式:就是把一件工作分别经过链上的各个节点,让这些节点依次处理这个工作,和装 ...

  3. mybatis源码学习:一级缓存和二级缓存分析

    目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...

  4. mybatis源码学习:基于动态代理实现查询全过程

    前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...

  5. mybatis源码学习:插件定义+执行流程责任链

    目录 一.自定义插件流程 二.测试插件 三.源码分析 1.inteceptor在Configuration中的注册 2.基于责任链的设计模式 3.基于动态代理的plugin 4.拦截方法的interc ...

  6. mybatis源码学习(一) 原生mybatis源码学习

    最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...

  7. Mybatis源码学习第六天(核心流程分析)之Executor分析

    今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...

  8. Mybatis源码学习之DataSource(七)_1

    简述 在数据持久层中,数据源是一个非常重要的组件,其性能直接关系到整个数据持久层的性能.在实践中比较常见的第三方数据源组件有Apache Common DBCP.C3P0.Proxool等,MyBat ...

  9. Mybatis源码学习第八天(总结)

    源码学习到这里就要结束了; 来总结一下吧 Mybatis的总体架构 这次源码学习我们,学习了重点的模块,在这里我想说一句,源码的学习不是要所有的都学,一行一行的去学,这是错误的,我们只需要学习核心,专 ...

随机推荐

  1. Python人脸识别 + 手机推送,老板来了你就会收到短信提示

  2. 在Linux系统中安装Tomcat详细教程

    首先在官网下载jdk和Tomcat的压缩包 这里下载jdk-8u241-linux-x64 .tar.gz 和apache-tomcat-8.5.50.tar.gz 然后解压jdk压缩包 tar –z ...

  3. 2020-04-07:假如你们系统接收十几种报文,用什么方式对应的各自的service,总不能都用if-else判断吧

    福哥答案2020-04-08: 策略,工厂.

  4. P、NP、NPC问题详解

    转载地址 https://blog.csdn.net/bcb5202/article/details/51202589 P.NP.NPC 概念 > P问题:能够在多项式时间内解决的决策问题. - ...

  5. 解决用anaconda安装scrapy后,在使用scrapy时报错

    python版本为3.7 因为用anaconda安装scrapy非常方便,会自动下载所依赖的包, 所以就使用anaconda安装scrapy, 非常舒服,安装很成功 conda install scr ...

  6. Js~对键值对操作

    键值对主要是面向对象语言里的字典,或者叫哈希表,它通过键(key)可以直接访问到值(value),所以它查找的时间复杂度是O(1),即一次查找即可找到目标:在.net里有Dictionary,而在ja ...

  7. [netty4][netty-handler]netty之idle handler处理

    初始化时记录idle时间,并启动一个延时任务,延时时间为idle时间,延时任务是io.netty.handler.timeout.IdleStateHandler.AllIdleTimeoutTask ...

  8. kafka-clients 1.0 高阶API消费消息(未完)

    消费消息的请求(按序) org/apache/kafka/common/requests/RequestHeader org/apache/kafka/common/requests/ApiVersi ...

  9. 碰到 Json_CSRF 怎么办?

    前言 在最近挖洞的时候,老是碰到 POST 传参采用 JSON 格式,而不是传统的parameter=value的格式,之前也没接触过,所以也不知道该怎么搞,所以打算学习一下,此文作为一个笔记梳理. ...

  10. 【java】java获取JVM启动参数 System.getProperty

    java获取JVM启动参数 System.getProperty取 -D后的key即可 public class Test { public static void main(String[] arg ...