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

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

相关文章
|
4月前
|
SQL XML Java
MyBatis Mapper中使用limit参数的查询问题
总结而言,MyBatis中使用 `limit`参数的查询可以高度定制并且灵活,基于方法签名和XML映射文件的组合来达成多样化的查询需求。通过参数化查询和动态SQL,MyBatis可以有效地处理各种复杂情境下的数据库操作,并且将SQL语句的维护与业务代码的编写相分离,提升代码的可维护性和可阅读性。
466 13
|
7月前
|
SQL 存储 Java
Mybatis源码解析:详述初始化过程
以上就是MyBatis的初始化过程,这个过程主要包括SqlSessionFactory的创建、配置文件的解析和加载、映射文件的加载、SqlSession的创建、SQL的执行和SqlSession的关闭。这个过程涉及到了MyBatis的核心类和接口,包括SqlSessionFactory、SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、Configuration、SqlSession和Executor等。通过这个过程,我们可以看出MyBatis的灵活性和强大性,它可以很好地支持定制化SQL、存储过程以及高级映射,同时也避免了几
140 20
|
8月前
|
SQL XML Java
四、MyBatis获取参数值的两种方式(重点)
四、MyBatis获取参数值的两种方式(重点)
181 4
|
10月前
|
SQL Java 数据库连接
Mybatis拦截器实现公共字段填充
通过使用MyBatis拦截器,可以实现对公共字段的自动填充,简化代码,提高开发效率。拦截器通过拦截SQL操作,在插入和更新操作时自动填充公共字段,使得开发者不再需要手动设置这些字段。本文详细介绍了实现步骤,并通过示例代码展示了具体实现方法,希望能为您的开发工作提供实用的指导和帮助。
630 13
|
SQL Java 数据库连接
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
396 10
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
318 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
802 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
5月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1023 1
Spring boot 使用mybatis generator 自动生成代码插件
|
8月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
704 0