mybatis 插件的原理-责任链和动态代理的体现

【MyBatis系列9】只要五分钟,彻底搞懂MyBatis插件原理及PageHelper原理 MyBatis插件实现原理前言MyBatis中插件是如何实现的MyBatis插件的使用MyBatis插件实现原理插件的加载插件如何进行拦截拦截Executor对象其他对象插件解析插件执行流程假如一个对象被代理很多次PageHelper插件的使用PageHelper插件原理为什么PageHelper只对startPage后的第一条select语句有效不通过插件能否改变MyBatis的核心行为总结 前言 提到插件,相信大家都知道,插件的存在主要是用来改变或者增强原有的功能,MyBatis中也一样。然而如果我们对 阅读详情

责任链设计模式理解起来很简单, 网上找个例子看看即可。

mybatis 插件的原理使用的是动态代理和责任链来实现的。

1 拦截哪些方法

可以通过注解 Intecepts 和 Signature 来进行指定拦截哪些方法。 然而, 并不是说所有的方法都可以拦截的。

mybatis 拦截器所拦截的方法, 有如下类型:

1\. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2. ParameterHandler (getParameterObject, setParameters)
3. ResultSetHandler (handleResultSets, handleOutputParameters)
4. StatementHandler (prepare, parameterize, batch, update, query)

为什么说可以拦截的方法是这些呢?

在 mybatis 中, 以上几个类是 SqlSession 的四大对象。 SqlSession 通过这些对象实现对数据库的操作, 结果的处理。 因此, 从流程上来说, 是拦截这几个对象中的方法是有非常重要的作用的。

而在源码上的体现呢, 就在 Configuration 类中, 这个类的重要性不做过多的阐述, 可以看看前面的文章。

在总 xml 解析成 Configuration 过程中, 需要 new 出以上的几个类。而以上的几个类在后面都会调用 interceptorChain#pluginAll 方法。

2 如何代理

public class InterceptorChain {

  /**
   * 拦截器列表
   */
  private final List<Interceptor> interceptors = new ArrayList<>();

  public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

  /**
   * 添加拦截器
   *
   * @param interceptor
   */
  public void addInterceptor(Interceptor interceptor) {
    interceptors.add(interceptor);
  }

  /**
   * 获取拦截器列表
   *
   * @return
   */
  public List<Interceptor> getInterceptors() {
    return Collections.unmodifiableList(interceptors);
  }

}

可以看到, 其会将调用所有拦截器的 plugin 方法, 层层代理之后返回最终的代理对象。 要注意这里的层层代理。

如果有 A、B、C 三个拦截器(签名相同), 则在此时, 会被层层封装。 最后执行的时候, 是 A>B>C> target.proceed() >C>B>A.

3 代理对象

InterceptorChain 会调用每个拦截器中的 plugin 方法。该方法是会返回相应的代理对象的。

/**
 * 拦截器接口
 *
 * @author Clinton Begin
 */
public interface Interceptor {

  /**
   * 执行拦截逻辑的方法
   *
   * @param invocation 调用信息
   * @return 调用结果
   * @throws Throwable 异常
   */
  Object intercept(Invocation invocation) throws Throwable;

  /**
   * 代理
   *
   * @param target
   * @return
   */
  Object plugin(Object target);

  /**
   * 根据配置来初始化 Interceptor 方法
   * @param properties
   */
  void setProperties(Properties properties);

}

其中的 plugin 是需要我们来实现的。 而 mybatis 也给我们提供了很方便的方法。

  public static Object wrap(Object target, Interceptor interceptor) {
    // 获取类型及对应的方法信息
    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;
  }

我们在重写 plugin 方法时, 只需要调用上面这个方法即可。 其会返回 Plugin 这个类的一个对象。

public class Plugin implements InvocationHandler
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      // 获取方法所在类中, 可以被拦截的所有的方法
      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      // 如果需要被拦截, 则调用 interceptor.intercept
      if (methods != null && methods.contains(method)) {
        return interceptor.intercept(new Invocation(target, method, args));
      }
      // 没有被拦截则正常调用
      return method.invoke(target, args);
    } catch (Exception e) {
      throw ExceptionUtil.unwrapThrowable(e);
    }
  }

由于 JDK 的动态代理是接口级别的。 因此, 其代理了类的所有接口的方法。 然而并不是所有的方法都是需要被代理的, 因此, 在方法中通过注解中的签名信息进行区分。

4 责任链设计模式

在插件的使用过程中, 责任链设计模式体现在动态代理的层层嵌套的代理增强之中。 体现在interceptorChain#pluginAll 方法中。 调用时会层层的进行代理。 mybatis 插件的原理-责任链和动态代理的体现

MyBatis源码剖析 - MyBatis 插件之拦截器(Interceptor)实现原理 在上一篇文章:MyBatis 教程 - MyBatis插件(Plugins)开发 中已经介绍了如何去开发一个MyBatis 插件,本文将结合MyBatis 源码来揭秘MyBatis Plugins内部实现原理。Mybatis3 插件采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的)。本文分析使用的MyBatis 源代码版本为3. 阅读详情

相关推荐

从零构建AI智能体:基于opencode框架的Agent开发全流程指南

AI智能体(AI Agent)作为人工智能领域的重要发展方向,正从概念走向工程实践。其核心原理在于赋予AI自主规划、执行和迭代的能力,使其不再局限于简单的问答,而是能够理解复杂目标、分解任务、调用工具并完成闭环。这一技术价值在于将AI从“对话伙伴”升级为“执行伙伴”,极大地拓展了自动化边界,在智能客服、数据分析、自动化运维等场景展现出巨大潜力。本文聚焦于如何利用opencode这一热门开发框架,快速构建具备实际能力的智能体。通过拆解其核心组件如技能库、规划器与运行时,并结合具体实践案例,系统阐述了从环境搭建

weixin_29055699的博客 439

Mybatis插件运行原理-动态代理

Myabtis插件运行原理

weixin_42595206的博客 495

基于单片机电能质量检测仪设计

*单片机设计介绍,基于单片机电能质量检测仪设计。

2201_75940997的博客 1206

Mybatis插件原理(代理+责任链模式)

Mybatis插件原理以及实现,从设计模式出发,一步一步理解其原理

阿鹏的博客 889

Maxwell中铜导体热损计算的关键步骤与技巧

本文详细介绍了在Maxwell软件中准确计算铜导体热损的关键步骤与实用技巧。重点阐述了如何正确设置涡流场求解器、启用涡流效应、根据工作频率计算并应用肌肤深度以指导网格剖分,以及准确施加激励和定义电流回路。文章还强调了使用温度相关材料属性和进行后处理验证的重要性,旨在帮助工程师获得可靠的热损计算结果,优化产品设计。

weixin_29232121的博客 498

Zabbix在Ubuntu 22.04上的性能优化与监控实战:从基础安装到高级配置

本文详细介绍了在Ubuntu 22.04系统上部署和优化Zabbix监控系统的完整流程,从基础安装到高级配置。内容包括MySQL数据库设置、Zabbix服务器与Web前端优化、性能调优策略以及实战监控场景应用,帮助用户构建高效的企业级监控解决方案。

sss66的博客 895

手写MyBatis第56弹:动态代理与责任链的完美结合MyBatis插件架构

MyBatis插件机制深度解析:从原理到实战应用 本文深入剖析了MyBatis强大的插件机制实现原理。插件机制基于动态代理和责任链模式,通过Interceptor接口实现对四大核心组件的非侵入式扩展。文章详细解析了InterceptorChain、Plugin等核心组件的工作原理,展示了插件从配置到执行的完整流程,并提供了性能监控插件的开发实例。同时总结了插件开发中的性能优化、线程安全等注意事项,以及分页、数据权限等典型应用场景。MyBatis插件机制巧妙结合了设计模式,为框架功能扩展提供了灵活高效的解决方

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 1668

CFturbo 2024保姆级教程:从流量扬程到三维叶轮,手把手搞定离心泵水力设计

本文提供CFturbo 2024离心泵水力设计的全流程实战指南,从流量扬程参数输入到三维叶轮模型导出,详细解析设计步骤与优化技巧。涵盖叶轮尺寸确定、子午面型线设计、叶片角度调整等关键环节,帮助工程师高效完成CAE辅助的离心泵水力设计,提升设计质量与效率。

weixin_42569329的博客 936

MyBatis实现原理

首先,您需要定义一个接口,代理将对其进行实现。下面不属于动态代理,定义一个类,封装对象反射执行方法/*** 目标对象*//*** 执行的方法*//*** 方法的参数*//*** 执行目标对象的方法*//*** 具体拦截处理,目标对象封装到Invocation*//*** 插入目标类,创建代理对象*/

m0_50149847的博客 2904

GAN模型中的常见变体有哪些,如DCGAN、WGAN和CGAN等?

生成对抗网络(GAN)是一种强大的深度学习模型,它由生成器和判别器两个网络组成,通过对抗训练的方式实现生成数据的能力。随着研究的发展,出现了许多GAN的变体,每个变体都有其独特的改进和特点。

huidhsu的博客 2262

手把手教你模拟登录豆瓣并爬取个人书影音数据:从Cookie解析到反爬攻防实战

在开始写代码之前,先明确我们需要的工具。:建议用3.10以上版本,方便使用一些新特性(如match语句)httpx:比requests更现代,支持HTTP/2,异步性能强,连接池复用好:解析HTML,语法简单,容错性强selenium:仅用于处理登录时的滑块验证(模拟真人)pandas:最终数据清洗和导出Excel/CSVretrying:自动重试机制,应对临时封禁:随机UA,降低特征lxml:作为BeautifulSoup的解析器,速度快为什么不只用requests?

2201_76125261的博客 578

MyBatis——MyBatis插件原理

本博文主要介绍MyBatis插件机原理,帮助大家更好的理解和学习MyBatis。

庄小焱 2138

18. 从 SAP Fiori Elements List Report 中的图片显示,谈谈背后的 XML Template 设计机制

至此,Fiori Elements List Report 这个模版里,图片显示的原理,笔者已经从开发人员层面需要定义的注解,和 Fiori Elements 框架层面如何解析这些注解,这两方面做了深入介绍。从本文开始,我们从 Fiori Elements 预制的标准 XML Template 模版的设计,来介绍我们在最终 Fiori Elements 页面看到的产品图标,是如何渲染出来的。但是,List Report 里产品的图标显示,到底是上面这些 XML 文件里的哪一个里定义的呢?

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 607

讲一下Mybatis的插件原理

MyBatis 的插件机制是其核心扩展点之一,基于和实现,允许开发者在 SQL 执行的关键节点插入自定义逻辑(如性能监控、SQL 改写、数据加密等)。Executor:执行 SQL(增删改查、事务):处理 SQL 语法(预编译、参数设置):处理 SQL 参数:处理结果集映射插件通过代理对象拦截目标方法,在方法执行前后插入自定义逻辑。所有配置的插件存储在中,按配置顺序形成责任链。每个插件的plugin()方法调用Plugin.wrap()生成代理对象。

tschen的博客 1041

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

MyBatis插件开发与源码解析:基于动态代理的责任链机制

MyBatis插件机制通过动态代理和责任链模式,在不修改源码的情况下扩展框架功能。核心实现包括Interceptor接口和@Intercepts/@Signature注解,利用Plugin类创建JDK动态代理,形成多层代理链。开发示例展示了SQL执行时间统计插件的实现,包括拦截方法、配置注册等。源码解析揭示了插件初始化、代理创建和方法执行的底层机制。该设计既保证了框架稳定性,又提供了灵活扩展能力,但需注意方法过滤精确性和性能影响。

趁年轻,多去失败 643

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Mybatis 的插件运行原理

MyBatis 插件机制提供了一种强大的方式来拦截和增强 SQL 执行过程。通过实现接口,开发者可以轻松地编写自定义插件,以满足各种业务需求。插件的运行依赖于 Java 的动态代理机制,并且采用了责任链模式,使得多个插件能够按顺序叠加效果。在实际应用中,MyBatis 插件可以用于记录日志、监控性能、修改 SQL 语句等多种场景。

Flying_Fish_roe的博客 857

Mybatis的插件原理

MyBatis插件机制基于拦截器和动态代理实现,通过责任链模式为四大核心组件(Executor、StatementHandler等)添加增强逻辑。插件需实现Interceptor接口,在intercept方法中编写自定义逻辑(如SQL改写、日志记录等),并通过plugin方法生成代理对象。MyBatis初始化时会按配置顺序将插件层层包装到目标对象上,形成调用链。执行时方法调用会依次经过各插件的拦截逻辑,最后到达原始方法。这种机制实现了AOP风格的横切功能,典型应用包括SQL日志、分页、审计等。开发插件时需通

2303_77517907的博客 737

Mybatis插件原理(代理+责任链)

Mybatis插件原理 在实际开发过程中,我们经常使用的Mybaits插件就是分页插件了,通过分页(例如 PageHelper)插件我们可以在不用写count语句和limit的情况下就可以获取分页后的数据,给我们开发带来很大的便利。除了分页,插件使用场景主要还有更新数据库的通用字段,分库分表,加解密等的处理。 JDK动态代理+责任链设计模式 Mybatis的插件其实就是个拦截器功能。它利用JDK动态代理和责任链设计模式的综合运用。采用责任链模式,通过动态代理组织多个拦截器,通过这些拦截器你可以做一些你想做的

qq_44056652的博客 406

MyBatis插件开发原理

一、前言 MyBatis采用责任链模式,通过动态代理组织多个插件(拦截器),通过这些插件可以改变MyBatis的默认行为(诸如SQL重写之类的),由于插件会深入到MyBatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件。 MyBatis在四大对象的创建过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,而实现目标对象在执行目标方法之前进行拦截的...

Java小蚂蚁 3153
上一篇: 应届毕业生面试第一句话:工资不到一万免谈,HR:我当时就懵了
下一篇: 10张流程图+部署图,讲透单点登录原理与简单实现!
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值