mybatis拦截器执行原理

news2025/1/11 0:15:48

title: “mybatis拦截器执行过程”
createTime: 2021-12-08T12:19:57+08:00
updateTime: 2021-12-08T12:19:57+08:00
draft: false
author: “ggball”
tags: [“mybatis”]
categories: [“java”]
description: “mybatis拦截器执行过程”

m[toc]

mybatis的拦截器本人平时也很少用到,没了解之前,也只是知道运用到了动态代理用来增强方法的功能,但是不了解其中的原理。为了更好的使用mybatis,这次,我记录下我所了解的mybatis的原理,本文不一定完全正确,可能有理解不到位的地方。

1、使用mybatis的拦截器

像平常使用mybatis框架时,如果哪句sql报错了,我们可以通过控制台或日志打印的sql去查看sql的问题,但是如果sql有太多的参数,其实是很不方便的,自己还得手动去把一个一个参数给设置上,有些浪费时间,这时候就可以利用mybatis的拦截器去帮我们把参数给设置上。

配置步骤

1.创建拦截器

@Intercepts({
        @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
createTime: 2021-12-08T12:19:57+08:00
updateTime: 2021-12-08T12:19:57+08:00
        @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class SlowSqlInterceptor implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
       // 主要逻辑 拼接参数到sql,并打印
    }

    @Override
    public Object plugin(Object target) {
        // 创建代理对象
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
      	// 设置属性
    }
}
/**
 * @author Clinton Begin
 */
public class Invocation {

  // 目标对象,即ParameterHandler、ResultSetHandler、StatementHandler或者Executor实例
  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;
  }

  /**
   * 执行目标方法
   * @return 目标方法执行结果
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   */
  public Object proceed() throws InvocationTargetException, IllegalAccessException {
    return method.invoke(target, args);
  }

}

拦截器类实现intercepter接口

  • intercepter方法主要写拦截方法的逻辑,Invocation对象主要有三个内置对象和proceed方法,proceed方法的作用就是用来执行代理对象的方法,对象target是被代理的对象实例,对象method是拦截方法,对象args是被调用方法传入的参数,很符合调用代理对象invoke方法的条件。

  • plugin方法接受实际对象,作用返回一个代理对象,这里是调用了Plugin提供的warp方法,方便创建代理对象,我们也可以自己写创建代理对象的代码

  • setProperties方法设置属性,当拦截器被扫描到时,会调用此方法。
    createTime: 2021-12-08T12:19:57+08:00
    updateTime: 2021-12-08T12:19:57+08:00

2.mybatis配置文件配置插件

image-20211204171440931

2、mybatis的拦截器如何创建的

image-20211206122358988

image-20211206122417844

  1. configuration创建时,会去扫描配置文件的<plugin>标签
  2. 获取<plugin>标签的interceptor属性
  3. 获取拦截器属性,转换为Properties对象
  4. 创建拦截器实例 利用TypeAliasRegistry的resolveAlias方法,将传进来的别名,判断如果别名在TYPE_ALIASES里面,则直接获取类对象,如果不是则反射获取类对象
  5. 设置拦截器实例属性信息 将第三步的properties属性添加到拦截器实例里面
  6. 將拦截器实例添加到拦截器链中 (拦截器在configuration里面)

3、mybatis的拦截器在哪些时机会被使用到

在Configuration类的

newParameterHandler()、newResultSetHandler()、newStatementHandler()、newExecutor()

这些工厂方法中,都调用了InterceptorChain对象的pluginAll()方法。-

image-20211206140008644

image-20211206140028014

image-20211206140042350

image-20211206135945837

image-20211206100432298

  /**
   * 该方法用于创建Executor、ParameterHandler、ResultSetHandler、StatementHandler的代理对象
   Plugin.warp()方法首先获取自定义的拦截类上的@Signature注解上的信息并存入map,那就知道了要拦截哪些对象地哪些方法,然后判断传入的target对象是否满足拦截对象的类型,满足则创建代理对象,不满足则直接返回原对象。
   * @param target
   * @param interceptor
   * @return
   */
  public static Object wrap(Object target, Interceptor interceptor) {
    // 调用getSignatureMap()方法获取自定义插件中,通过Intercepts注解指定的方法
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

添加拦截方法

这里拿在执行器上添加拦截方法举例:

1. mybatis在创建sqlSession时,会创建执行器Executor,同时调用拦截器的pluginAll方法,调用每个拦截器的plugin方法,这个方法主要是创建代理对象,将代理功能增强到被拦截的方法上。
2. Plugin.warp()方法首先获取自定义的拦截类上的@Signature注解上的信息并存入map,那就知道了要拦截哪些对象地哪些方法,然后判断传入的target对象是否满足拦截对象的类型,满足则创建代理对象,不满足则直接返回原对象。

拦截器被使用到的过程

image-20211206155858474

image-20211206160023347

image-20211206160054776

image-20211206160144051

image-20211206160202063

image-20211206160249200

image-20211206160309014

image-20211206160510749

createTime: 2021-12-08T12:19:57+08:00
updateTime: 2021-12-08T12:19:57+08:00
createTime: 2021-12-08T12:19:57+08:00
updateTime: 2021-12-08T12:19:57+08:00
3. configuration创建statementHandler代理对象,同样有关于statementHandler的拦截器,也会创建代理类
4. statementHandler执行query方法,如果statementHandler对象是代理对象,则进入Plugin的invoke方法,如果当前执行的方法符合被拦截的方法的要求,那么就会执行拦截方法,否则不执行拦截方法,如果statementHandler对象不是代理对象,直接执行原方法。

4、总结

原来以为拦截器只是简单的使用下动态代理,看了mybatis的拦截器发现,一个经得起捶打的功能是不可能那么简单的,里面用到了动态代理解决mapper的实现问题,适配器模式用来解决结果对象,参数对象的映射,而且在我看来configuration类做了太多的工作,很多初始化的数据都能在里面找到,只要持有configuration对象,很多数据都可以直接拿到,避免现拿现查的麻烦。

器模式用来解决结果对象,参数对象的映射,而且在我看来configuration类做了太多的工作,很多初始化的数据都能在里面找到,只要持有configuration对象,很多数据都可以直接拿到,避免现拿现查的麻烦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1035705.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】链表--单链表

目录 一 概念及结构 二 单链表的实现 1 包含接口(SList.h) 2 打印和创造节点&#xff08;扩容&#xff09;&#xff08;SList.c) 3 尾插&#xff08;SList.c) 4 头插&#xff08;SList.c) 5 尾删&#xff08;SList.c) 6 头删&#xff08;SList.c) 7 在pos前插入x&…

大数据从入门到精通(超详细版)之Hive的案例实战,ETL数据清洗!!!

前言 嗨&#xff0c;各位小伙伴&#xff0c;恭喜大家学习到这里&#xff0c;不知道关于大数据前面的知识遗忘程度怎么样了&#xff0c;又或者是对大数据后面的知识是否感兴趣&#xff0c;本文是《大数据从入门到精通&#xff08;超详细版&#xff09;》的一部分&#xff0c;小…

安全生产知识竞赛活动小程序界面分享

安全生产知识竞赛活动小程序界面分享

SCR截面速度、氨氮比等标准及相对标准偏差计算

SCR截面速度、氨氮比等标准及相对标准偏差计算 # -*- coding: utf-8 -*- """ 联系QQ:3123575367&#xff0c;专业SCR脱硝仿真。 Created on Wed Sep 20 20:40:30 2023 该程序用来处理fluent通过xyplot导出的数据&#xff0c;可计算标准偏差SD、相对标准偏差RSD…

linux 安装 wordpress

文章目录 linux 安装 wordpress1. wordpress 简介2. wordpress功能和特点3. 部署要求4. 环境搭建4.1 部署 nginx4.1.1 新增配置文件 4.2 部署 PHP74.2.1 查看当前版本4.2.2 YUM 安装 PHP74.2.3 查看 PHP 版本4.2.4 启动PHP-FPM4.2.5 修改配置文件4.2.6 重启服务 4.3 部署 mysql…

Spring事务2+银行转账拓展

前言 Transactional()内可以写的属性 一、Dao层的更新 public interface LogDao {//#{}符号取的是接口方法中的形参 now()方法直接调用的内置函数Insert("insert into log (info,createDate) values(#{info},now())")void log(String info); }二、LogService层…

【Element】通知 Notification

ElementUI 弹出通知 created() {const h this.$createElementconst that thisthis.$notify({onClose: function () {that.do()},type: warning,duration: 5000, // 5秒后隐藏offset: 0, // 距离顶部dangerouslyUseHTMLString: false, showClose: false,customClass: notify-…

索引(含B树、B+树)

1、索引&#xff08;index&#xff09; 索引是在数据库表的字段上添加的&#xff0c;是为了提高查询效率存在的一种机制。 一张表的一个字段可以添加一个索引&#xff0c;当然&#xff0c;多个字段联合起来也可以添加索引。 索引相当于一本书的目录&#xff0c;是为了缩小扫描…

Nginx 防止跨站脚本 Cross-Site Scripting (XSS)

1、修改 nginx 配置 在 nginx.conf 配置文件中&#xff0c;增加如下配置内容&#xff1a; add_header X-XSS-Protection "1; modeblock";X-XSS-Protection 的字段有三个可选配置值&#xff0c;说明如下&#xff1a; 0&#xff1a; 表示关闭浏览器的XSS防护机制&…

计算机专业毕业设计项目推荐08-英语在线点读平台(SpringBoot+Vue+MongoDB)

英语在线点读平台&#xff08;SpringBootVueMongoDB&#xff09; **介绍****系统总体开发情况-功能模块****各部分模块实现** 介绍 本系列(后期可能博主会统一为专栏)博文献给即将毕业的计算机专业同学们,因为博主自身本科和硕士也是科班出生,所以也比较了解计算机专业的毕业设…

华为认证HCIP知识点

文章目录 前言考试内容数据通信领域各场景通用核心知识OSPFIS-ISBGPIGMPICMP 数据通信领域路由交换高阶知识大数据技术Hadoop 总结 前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联系后即刻更改 科普&#xff1a; 考试内容 参考网址 HCIP认证主要定位于中小型网…

Spring面试题7:面试官:Spring是如何进行异常处理的呢?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring是如何进行异常处理的呢? Spring通过异常处理机制来处理应用程序中的异常。它提供了多种方式来处理异常,包括以下几种: 声明式事务管理:…

实战案例:场景测试之ATM机取款业务测试

本期&#xff0c;我们通过经典案例——ATM机的操作&#xff0c;来为大家详细说说如何撰写对应的测试用例。 案例 在我们日常生活中&#xff0c;ATM机是个大家都非常熟悉的事物。银行为例提高工作效率&#xff0c;方便客户随时办理基础的储蓄和提现业务&#xff0c;于是&#…

Qt5开发及实例V2.0-第二十章-Qt.QML动画特效

Qt5开发及实例V2.0-第二十章-Qt.QML动画特效 第20章 QML动画特效20.1 QML动画元素20.1.1 PropertyAnimation元素20.1.2 其他动画元素20.1.3 Animator元素 20.2 动画流UI界面20.2.1 状态和切换 20.3 图像特效20.3.1 3D旋转20.3.2 色彩处理 20.4 Qt 5.5&#xff08;Qt Quick Extr…

web前端float布局、flex布局

1、float布局 <!DOCTYPE html> <html> <head><title>Login Page</title><style>body {font-family: Arial, sans-serif;background-color: #f3f3f3;}.container {max-width: 400px;margin: 0 auto;padding: 40px;background-color: #fff;…

变压器(电抗器) 红外测温作业指导书

1 范围 本标准化作业指导书规定了变压器(电抗器)红外测温(一般检测)工作的准备工作、测温流程图、 现场操作方法、测温周期和标准、测温记录管理等要求。 本标准化作业指导书适用于指导变压器(电抗器)红外测温的一般性检测工作。 2 规范性引用文件 下列文件对于本文件的应用…

我们为什么要做一名系统管理员?

我们为秩序而战&#xff0c;而服务器大叔则需要你成为系统管理员。这是个很好的机会&#xff0c;因为你已经管理过你有的那些系统&#xff0c;你本可以不需酬劳地管理那些日逐一日地运行的系统。但还是有一些面试官&#xff0c;愿意拿一笔很不错的薪水来找一些人去管理他们的系…

最频繁被问到的SQL面试题

面试感叹失败的原因可能有很多&#xff0c;而做成的道路只有⼀条&#xff0c;那就是不断积累。纯手工的8291字的SQL面试题总结分享给初学者&#xff0c;俗称八股文&#xff0c;期待对新手有所帮助。 窗口函数题 窗口函数其实就是根据当前数据, 计算其在所在的组中的统计数据。…

计算机毕业设计 基于SpringBoot的4S店车辆管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…