当前位置: 首页 > news >正文

Mybatis执行SQL流程(四)之MyBatis中JDK动态代理

文章目录

      • 动态代理
        • 代理对象的创建过程

动态代理

Mybatis使用JDK动态代理为Mapper 接口创建代理对象。当调用Mapper接口方法时,实际上调用的是代理对象的方法,代理对象会将方法调用转发给Mybatis的核心执行器。

  • MapperProxy:实现了 InvocationHandler 接口,是Mybatis动态代理的核心类
  • MapperProxyFactory :负责创建Mapper 接口的代理对象
  • MapperRegistry:管理所有Mapper 接口及其对应的代理工厂。
代理对象的创建过程

1、初始阶段:

  • Springboot项目启动时解析所有的Mapper接口和映射文件
  • 为每个Mapper接口创建MapperProxyFactory,并注册到 MapperRegistry:Map<Class<?>, MapperProxyFactory<?>> knownMappers

2、获取Mapper 实例:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 大致实现内容如下:
  • 通过MapperRegistry 获取对应的 MapperProxyFactory

  • 使用MapperProxyFactory 创建代理对象

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); // 获取对应的 MapperProxyFactoryif (mapperProxyFactory == null) {throw new BindingException("Type " + type + " is not known to the MapperRegistry.");}try {return mapperProxyFactory.newInstance(sqlSession); // MapperProxyFactory 创建代理对象} catch (Exception e) {throw new BindingException("Error getting mapper instance. Cause: " + e, e);}}
// 其中newInstance:
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);// 构建代理类class,并实例化一个对象。JDK动态代理的具体流程见另一篇文章。
// 动态代理:所有 Mapper 方法调用会被拦截并转发给 MapperProxy.invoke()。 此处涉及到代理类的源码,见后续内容。

JDK动态代理的具体流程见另一篇文章。
此处做简单的说明:

为接口生成一个实现类的class文件的字节码,并加载到JVM中,在字节码文件中,重写了接口的方法:

public final void methodName() {super.h.invoke(this, MethodObject, // 对应方法的Method对象args);        // 方法参数
}

所以当使用代理对象调用接口中的方法时,执行的其实是invocationHandler对象中的invoke方法,而此时invocationHandler对象是mapperProxy对象。具体执行内容见MapperProxy。

3、方法调用流程

当调用mapper接口方法时:

  • 代理对象拦截方法调用
  • 创建MapperMethod对象(封装了SQL命令和执行逻辑)
  • 执行 MapperMethod.execute()方法
  • 根据方法类型(select/insert/update/delete)调用SqlSession的相应方法
  • 返回执行结果
http://www.lryc.cn/news/625587.html

相关文章:

  • 【HTML】3D动态凯旋门
  • Leetcode 343. 整数拆分 动态规划
  • C++入门自学Day14-- Stack和Queue的自实现(适配器)
  • 神经网络中的那些关键设计:从输入输出到参数更新
  • 面试题储备-MQ篇 3-说说你对Kafka的理解
  • 图论\dp 两题
  • 设计模式笔记_行为型_命令模式
  • 【React】事件绑定和组件基础使用
  • 从线性回归到神经网络到自注意力机制 —— 激活函数与参数的演进
  • java基础(十二)redis 日志机制以及常见问题
  • 2025年12大AI测试自动化工具
  • 多模态大模型应用落地:从图文生成到音视频交互的技术选型与实践
  • 【模块系列】STM32W25Q64
  • TDengine IDMP 运维指南(4. 使用 Docker 部署)
  • 第六天~提取Arxml中CAN物理通道信息CANChannel--Physical Channel
  • 5. Dataloader 自定义数据集制作
  • C语言基础:(十八)C语言内存函数
  • java17学习笔记-Deprecate the Applet API for Removal
  • 算法——质数筛法
  • yolov5s.onnx转rk模型以及相关使用详细教程
  • 假设检验的原理
  • python的社区互助养老系统
  • word如何转换为pdf
  • MFC中使用EXCEL的方法之一
  • ios使用saveVideoToPhotosAlbum 保存视频失败提示 invalid video
  • 基于单片机的智能声控窗帘
  • 437. 路径总和 III
  • Qt 插件开发全解析:从接口定义,插件封装,插件调用到插件间的通信
  • SWMM排水管网水力、水质建模及在海绵与水环境中的应用
  • 第5章 高级状态管理