干翻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:乐观锁

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

相关文章
|
3月前
|
Java 数据库连接 数据库
mybatis查询数据,返回的对象少了一个字段
mybatis查询数据,返回的对象少了一个字段
249 8
|
3月前
|
SQL XML Java
mybatis-源码深入分析(一)
mybatis-源码深入分析(一)
|
25天前
|
SQL Java 数据库连接
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
|
2月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
53 10
|
3月前
|
SQL XML Java
mybatis复习02,简单的增删改查,@Param注解多个参数,resultType与resultMap的区别,#{}预编译参数
文章介绍了MyBatis的简单增删改查操作,包括创建数据表、实体类、配置文件、Mapper接口及其XML文件,并解释了`#{}`预编译参数和`@Param`注解的使用。同时,还涵盖了resultType与resultMap的区别,并提供了完整的代码实例和测试用例。
mybatis复习02,简单的增删改查,@Param注解多个参数,resultType与resultMap的区别,#{}预编译参数
|
3月前
|
SQL Java 数据库连接
解决mybatis-plus 拦截器不生效--分页插件不生效
本文介绍了在使用 Mybatis-Plus 进行分页查询时遇到的问题及解决方法。依赖包包括 `mybatis-plus-boot-starter`、`mybatis-plus-extension` 等,并给出了正确的分页配置和代码示例。当分页功能失效时,需将 Mybatis-Plus 版本改为 3.5.5 并正确配置拦截器。
977 6
解决mybatis-plus 拦截器不生效--分页插件不生效
|
2月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
76 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
2月前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
162 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
4月前
|
Web App开发 前端开发 关系型数据库
基于SpringBoot+Vue+Redis+Mybatis的商城购物系统 【系统实现+系统源码+答辩PPT】
这篇文章介绍了一个基于SpringBoot+Vue+Redis+Mybatis技术栈开发的商城购物系统,包括系统功能、页面展示、前后端项目结构和核心代码,以及如何获取系统源码和答辩PPT的方法。
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
145 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
下一篇
DataWorks