干翻Mybatis源码系列之第十一篇:Mybatis拦截器获取被拦截对象的方法和参数

简介: 干翻Mybatis源码系列之第十一篇:Mybatis拦截器获取被拦截对象的方法和参数

给自己的每日一句

不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽都顺利。

如何找到孙帅本人

本文内容整理自《孙哥说Mybatis系列视频课程》,老师实力十分雄厚,B站搜孙帅可以找到本人,视频中有老师的微信号。

前言

拦截器并不是简单对Dao层对象进行拦截,而是更加偏向底层的拦截,拦截的是Executor和各种Handler。

在这四个里边,最终要的是Executor和StatementHandler,当然最常用的是StatementHandler因为它是与数据库实际交互的,更加底层。

我们真正在StatementHandler开启的任务是拦截操作,拦截器的就是增删改查的处理,是通过StatementHandler其中的两个方法体现的,query和update方法

如果我们方法都要拦截,最好我们直接拦截prepare方法,因为他有两个好处,一个是prepare在update和query方法执行前执行,返回值是statement。另一个是prepare方法中的入参中有connection对象。所有JDBC的操作都是基于Connection,有了连接我们就有了一切。

一:拦截器获取拦截对象

答案是在intercepter方法当中:

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyMybatisInterceptor3 extends MyMybatisInterceptorAdapter {
    private static final Logger log = LoggerFactory.getLogger(MyMybatisInterceptor3.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (log.isDebugEnabled())
            log.debug("-----this is myMybatisInterceptor3-------");
        MetaObject metaObject = SystemMetaObject.forObject(invocation);
        String methodName = (String) metaObject.getValue("method.name");
        String sql = (String) metaObject.getValue("target.delegate.boundSql.sql");
        if (log.isDebugEnabled())
            log.debug("methodname is " + methodName + " sql is " + sql);
        return invocation.proceed();
    }
    @Override
    public void setProperties(Properties properties) {
    }
}

Invocation 对象源码

public class Invocation {
  private final Object target;
  private final Method method;
  private final Object[] args;
  public Invocation(Object target, Method method, Object[] args) {
    this.target = target;
    this.method = method;
    this.args = args;
  }
  public Object getTarget() {
    return target;
  }
  public Method getMethod() {
    return method;
  }
  public Object[] getArgs() {
    return args;
  }
  public Object proceed() throws InvocationTargetException, IllegalAccessException {
    return method.invoke(target, args);
  }
}

Invocation对象里边有一个target对象,代表的就是拦截器所拦截的目标

method所代表的就是我们拦截的方法。当前案例中对饮的就是prepare方法

Object[] args这个数据,代表的就是拦截方法的参数。

1:如果获取被拦截方法和参数

2:演示证明

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyMybatisInterceptor3 extends MyMybatisInterceptorAdapter {
    private static final Logger log = LoggerFactory.getLogger(MyMybatisInterceptor3.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (log.isDebugEnabled())
            log.debug("-----this is myMybatisInterceptor3-------");
        MetaObject metaObject = SystemMetaObject.forObject(invocation);
        String methodName = (String) metaObject.getValue("method.name");
        String sql = (String) metaObject.getValue("target.delegate.boundSql.sql");
        if (log.isDebugEnabled())
            log.debug("methodname is " + methodName + " sql is " + sql);
        return invocation.proceed();
    }
    @Override
    public void setProperties(Properties properties) {
    }
}
<plugins>
        <plugin interceptor="com.baizhiedu.plugins.MyMybatisInterceptor3"/>
    </plugins>

二:MetaObject

1:MetaObject简介

Mybatis封装的反射,进行导航式的数据取值与赋值。整个过程都是基于反射完成,十分简化开发。

MetaObject metaObject = SystemMetaObject.forObject(invocation);
        String methodName = (String) metaObject.getValue("method.name");
        String sql = (String) metaObject.getValue("target.delegate.boundSql.sql");
        log.debug("methodname is " + methodName + " sql is " + sql);

2:MetaObject代码展示

package org.apache.ibatis.reflection;
public class MetaObject {
  private final Object originalObject;
  private final ObjectWrapper objectWrapper;
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;
  private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    this.originalObject = object;
    this.objectFactory = objectFactory;
    this.objectWrapperFactory = objectWrapperFactory;
    this.reflectorFactory = reflectorFactory;
    if (object instanceof ObjectWrapper) {
      this.objectWrapper = (ObjectWrapper) object;
    } else if (objectWrapperFactory.hasWrapperFor(object)) {
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) {
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {
      this.objectWrapper = new BeanWrapper(this, object);
    }
  }

但凡是开发源框架,底层都会进行基本的封装:IO,反射,集合的操作都会进行封装。

三:如何使用Mybatis拦截器解决开发中的实际问题

在Mybatis开发中可能要

1:对SQL语句进行操作。

2:分页

3:乐观锁

在接下来的文章中,我们会对着实际开发中的三个问题,进行详细的说明。

相关文章
|
6天前
|
XML Java 数据库连接
Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发
【5月更文挑战第10天】Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发
18 6
|
6天前
|
XML Java 数据库连接
MyBatis 解决上篇的参数绑定问题以及XML方式交互
MyBatis 解决上篇的参数绑定问题以及XML方式交互
13 0
|
6天前
|
SQL 监控 Java
mybatis拦截器实现
mybatis拦截器实现
14 0
|
6天前
|
SQL Java 数据库连接
15:MyBatis对象关系与映射结构-Java Spring
15:MyBatis对象关系与映射结构-Java Spring
31 4
|
6天前
|
SQL Java 数据库连接
一文细说Mybatis八大核心源码
以上 是V哥给大家整理的8大核心组件的全部内容,为什么说选择 Java 就是选择未来,真正爱 Java 的人,一定喜欢深入研究,学习源码只是第一步,要有一杆子捅到操作系统才够刺激。
|
6天前
|
SQL 缓存 Java
|
6天前
|
XML Java 数据库连接
java对象有集合mybatis如何映射
java对象有集合mybatis如何映射
21 4
|
6天前
|
XML Java 数据库连接
探秘MyBatis:手写Mapper代理的源码解析与实现
探秘MyBatis:手写Mapper代理的源码解析与实现
21 1
|
6天前
|
SQL Java 数据库连接
深度解析MyBatis核心:探寻其核心对象的精妙设计
深度解析MyBatis核心:探寻其核心对象的精妙设计
25 1
深度解析MyBatis核心:探寻其核心对象的精妙设计
|
6天前
|
SQL Java 数据库连接
深入源码:解密MyBatis数据源设计的精妙机制
深入源码:解密MyBatis数据源设计的精妙机制
34 1
深入源码:解密MyBatis数据源设计的精妙机制