Mybatis中拦截器的简单实现方法

前言

需求驱动学习,最近一周组长让我在业务模块里加日志,经过与导师以及组长讨论决定用拦截器记录日志。周五下班前已经发了提测邮件。

虽然我知道 MyBatis 有这东西,但是没在实际情况中用过,心里有点虚2333……所以才有了此文的理解。

前世今生

它的本质就是 JDK 的动态代理。首先先来复习一下动态代理我贴了一段最常见的 JDK 动态代理的代码

//服务员的接口
public interface Waiter {
  void serve();
}
//服务员的实现
public class WaiterImpl implements Waiter {
  @Override
  public void serve() {
    System.out.println("服务中...");
  }
}
//需要代理的对象处理器
class WaitInvocationHandler implements InvocationHandler {
  private Waiter waiter;

  public WaitInvocationHandler(Waiter waiter1) {
    waiter = waiter1;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("你好");
    Object invoke = method.invoke(waiter, args);
    System.out.println("再见");
    return invoke;
  }
}
public class App {
  //普通的实现
  @Test
  public void fun() {
    Waiter waiter = new WaiterImpl();
    waiter.serve();
  }

  @Test
  public void fun1() {
    Waiter a = new WaiterImpl();
    ClassLoader classLoader = getClass().getClassLoader();
    Class[] classes = {Waiter.class};
    //生成代理对象
    Waiter waiterproxy = (Waiter) Proxy.newProxyInstance(classLoader, classes, new WaitInvocationHandler(a));
    waiterproxy.serve();
  }
}

拦截器

V1

我现在要在函数执行前后记录日志操作,考虑需要在代理方法那里定义个拦截器的接口,如下代码所示

//拦截器 V1 版本
public interface MyInterceptorV1 {
  void interceptor();
}
//代理对象变成这个
public class TargetProxyV1 implements InvocationHandler {

  private Target target;

  private MyInterceptorV1 myInterceptor;

  public TargetProxyV1(Target target, MyInterceptorV1 myInterceptor) {
    this.target = target;
    this.myInterceptor = myInterceptor;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    myInterceptor.interceptor();
    return method.invoke(target, args);
  }
}

这是最简单的版本,但是我们很多时候需要拦截参数等根据参数判断拦不拦截等,代码更新如下

public interface MyInterceptorV1 {
  void interceptor(Method method, Object[] args);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  myInterceptor.interceptor(method, args);
  return method.invoke(target, args);
}

V2

似乎上面的方案很完美

废话肯定不完美,不然怎么会有这段

没错,第二段代码并不是很优雅,有方法参数重复,可以考虑将三者抽出来,直接在拦截器的实现里写上 method.invoke(target, args); ,如下代码所示

@Getter
@Setter
@AllArgsConstructor
public class MyInvocation {
  private Object target;
  private Method method;
  private Object[] args;

  public Object proceed() throws InvocationTargetException, IllegalAccessException {
    return method.invoke(target, args);
  }
}
//没错这就是 V2 版本
public interface MyInterceptorV2 {
  Object interceptor(MyInvocation invocation) throws Throwable;
}

总结
Mybatis 的拦截器就是像我上面这么写的,

名字也跟我取得一样, 只是它更加复杂,能够通过注解区分拦截 update 操作和 query
等操作。

既完成了任务又巩固了原来的知识,这种感觉很棒,最关键的是还有钱拿……

本文代码

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis 允许使用插件来拦截的方法调用包括: Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) P

  • MyBatis拦截器实现分页功能实例

    由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能 现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践 既然是基于MyBatis 所以就先搭建一个Mybatis的小项目 1.01导入 mybatis和mysql的包 1.02.配置文件 Configuration.xml 中添加 <environments default="development"&

  • MyBatis拦截器实现分页功能的实现方法

    MyBatis拦截器实现分页功能的实现方法 前言: 首先说下实现原理.使用拦截器拦截原始的sql,然后加上分页查询的关键字和属性,拼装成新的sql语句再交给mybatis去执行. 除了业务代码之外,需要写的东西不多,提几个关键的: 1.分页对象Page类.给该对象设置一个当前页数(前端给).总记录数(拦截器内赋值)2个参数,他就能帮你计算出分页sql语句用的2个参数. /** * 分页对应的实体类 */ public class Page { /** * 总条数 */ private int t

  • Mybatis Interceptor 拦截器的实现

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件. 拦截器(Interceptor)在 Mybatis 中被当做插件(plugin)对待,官方文档提供了 Executor,ParameterHandler,ResultSetHandler,StatementHandler 共4种,并且提示"这些类中方法的细

  • Mybatis拦截器的实现介绍

     MyBatis介绍 MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .它支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的

  • java MyBatis拦截器Inteceptor详细介绍

    有许多java初学者对于MyBatis拦截器Inteceptor不是很了解,在这里我来为各位整理下篇关于java中MyBatis拦截器Inteceptor详解, 本文主要分析MyBatis的插件机制,实际就是Java动态代理实现的责任链模式实现. 根据官方文档.Mybatis只允许拦截以下方法,这个决定写拦截器注解签名参数. 代码如下 Executor (update, query, flushStatements, commit, rollback, getTransaction, close

  • Mybatis拦截器实现分页

    最终dao层结果: public interface ModelMapper { Page<Model> pageByConditions(RowBounds rowBounds, Model record); } 接下来一步一步来实现分页. 一.创建Page对象: public class Page<T> extends PageList<T> { private int pageNo = 1;// 页码,默认是第一页 private int pageSize = 1

  • java利用mybatis拦截器统计sql执行时间示例

    可以根据执行时间打印sql语句,打印的sql语句是带参数的,可以拷贝到查询分析器什么的直接运行 复制代码 代码如下: package mybatis; import java.text.DateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.Properties; import org.apache.ibatis.executor.Executor;import

  • MyBatis Excutor 拦截器的巧妙用法

    这里要讲的巧妙用法是用来实现在拦截器中执行额外 MyBatis 现有方法的用法. 并且会提供一个解决拦截Executor时想要修改MappedStatement时解决并发的问题. 这里假设一个场景: 实现一个拦截器,记录 MyBatis 所有的 insert,update,delete 操作,将记录的信息存入数据库. 这个用法在这里就是将记录的信息存入数据库. 实现过程的关键步骤和代码: 1.首先在某个 Mapper.xml 中定义好了一个往日志表中插入记录的方法,假设方法为id="insert

  • MyBatis拦截器:给参数对象属性赋值的实例

    该拦截器的作用:在进行增加.修改等操作时,给数据模型的一些通用操作属性(如:创建人.创建时间.修改人.修改时间等)自动赋值. 该实现是在DAO层拦截,即存入DB前最后一层.后经分析,不是很合理,改为在service层拦截,用spring AOP来实现了,该代码遂弃用.不过已经测试可用,记录备忘. package com.development; import java.lang.reflect.InvocationTargetException; import java.util.Date; i

随机推荐