MyBatis原理(四):MyBatis中代理模式的运用

Mybatis关于JDK动态代理的实现的总结 Mybatis关于JDK动态代理的实现的总结 前言 了解过Java关于JDK的动态代理之后,了解到平常用的Mybatis框架也是基于JDK动态代理实现对数据库的CRUD的,所以上网查资料,其中找到一片写得不错得博客觉得分析得已经很到位,本来想自己写一片文章的,由于自己学识尚浅,所以就索性站在巨人的肩膀上,去进行一个总结,其中有一节晦涩难懂的代码实在是看不懂,所以就放在一边了。虽然说没能写出一片分析... 阅读详情

问题

先来思考几个问题:

  1. 为什么我们在mybatis中只需要写一个dao层接口就可以直接调用方法,返回数据库查询结果呢?

一、JDK动态代理

先说出答案,MyBatis是使用JDK动态代理来设计的:

利用java.lang.reflect.Proxy对象实现,底层用到其实是反射。

  • 被代理对象必须实现接口(因为java类是单继承的,动态代理类在被创建后继承了Proxy类,所以目标对象必须实现接口,其实跟静态代理的条件差不多,只不过通过反射,很多东西可以动态执行,不需要手写)
  • static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )Proxy类的静态方法,ClassLoader ,指定类加载器,interfaces目标类实现的接口,InvocationHandler 这个类会对目标对象进行拦截,然后代理类使用反射来进行调用。例如下边的代码。

 

// jdk动态代理
public class ProxyFactory{
    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }
   //给目标对象生成代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始事务2");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");
                        return returnValue;
                    }
                }
        );
    }
}

 

 

上一篇我们已经知道了怎么样用SqlSession.selectList()来执行查询了,但是我们在做项目时,用的都是xxxMapper.selectByPriMary()来执行查询的,这个过程mybatis是怎么转换到使用sqlsession呢?

// 获取UserMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

我们就从getMapper去追源码就可以了。

// 1.可以看到是从configuration获取的
public <T> T getMapper(Class<T> type) {
    return configuration.<T>getMapper(type, this);
  }
// 2.configuration类的获取方法,mapperRegistry顾名思义是一个注册mapper的对象
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }
/* 3.mapperRegistry类的获取方法
 knownMappers是一个HashMap,在项目启动时会从配置文件中(配置的包扫描)
 将所有mapper全部放到这个map,key是Mapper的Class对象,value就是Mapper对应的MapperProxyFactory,
一个Mapper对应一个MapperProxyFactory*/
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

再看MapperProxyFactory对象的newInstance():

public T newInstance(SqlSession sqlSession) {
// MapperProxy对象是jdk代理的newProxyInstance()方法中用到的第三个参数,继承了InvocationHandler,会对mapper方法进行拦截,然后使用反射执行代理方法
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
// 调用重载方法
    return newInstance(mapperProxy);
  }
protected T newInstance(MapperProxy<T> mapperProxy) {
// 重点来了,看到jdk动态代理所用到的Proxy对象了么
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

再看MapperProxy类:

// 实现了InvocationHandler
public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -6424540398559729838L;
  private final SqlSession sqlSession;
  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethod> methodCache;

  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
    this.sqlSession = sqlSession;
    this.mapperInterface = mapperInterface;
    this.methodCache = methodCache;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 如果两者类型相同,那么直接用原对象执行
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
// 反射执行方法
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
// 甚至对执行过的方法进行了缓存,下次就不用再创建新的了
    final MapperMethod mapperMethod = cachedMapperMethod(method);
//  最后在execute()里边开始使用sqlSession调用查询、插入、删除等等了。
    return mapperMethod.execute(sqlSession, args);
  }

  private MapperMethod cachedMapperMethod(Method method) {
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
      methodCache.put(method, mapperMethod);
    }
    return mapperMethod;
  }

到此就追完了,但是我在写的过程中发现一个问题:

说好的JDK动态代理,目标类需要实现一个接口呢,为什么MyBatis的mapper没有实现呢,mapper本身就是接口还实现个啥。自己就是顶级接口,所以就不需要实现了,哈哈哈

Mybatis - 预编译的运用和原理 首先我们来说下预编译的一个背景:我们知道一条SQL语句到达Mysql之后,Mysql并不是会马上执行它,而是需要经过几个阶段性的动作(细节的可以查看Mysql复习计划(一)- 字符集、文件系统和SQL执行流程缓存的检查。解析器解析。优化器解析。执行器执行。那么这几个阶段肯定是需要一定的时间的。而有时候我们一条SQL语句可能需要反复的执行,只不过里面的参数可能不一样,比如where子句中的条件。如果每次都需要经过上面的几个步骤,那么效率就会下降。因此为了解决这种问题,就出现了预编译。 阅读详情

相关推荐

单相全桥逆变器中比例谐振(PR)控制的优化设计与实现

本文深入探讨了比例谐振(PR)控制在单相全桥逆变器中的优化设计与实现。通过对比PID控制,详细阐述了PR控制在50Hz基波频率处实现无静差跟踪和强抗干扰性的原理。文章提供了从理论建模、参数整定(Kp, Kr, ωc)到仿真验证的完整实战流程,并介绍了准比例谐振(QPR)控制以增强频率鲁棒性,以及多谐振点设计以抑制特定谐波等进阶优化方法,最终实现THD从3%降至1%以内的显著性能提升。

weixin_29056781的博客 176

MyBatis详解、静态代理与动态代理

MyBatis详解、静态代理与动态代理。

秦矜のblog 2020

距离多普勒谱(RD谱)绘制方法及理解

RD谱是信号处理领域常用的图形。原始信号往往是一维时域序列,如何将其二维化,并进行变换生成RD谱呢?由于刚刚接触,查阅了网络上、老师手里的资料,发现RD谱的绘制方法并不统一,有些存在一定问题。在此,将心得体会记录下来。

mddh_123的博客 3万+

Mybatis源码解析(八):Mapper代理原理

文章主要围绕着如下几个点,展开源码解析:是如何进行解析的?是如何生成的代理对象?是怎么完成的增删改查操作?标签配置的包名下的Mapper接口文件都会被加载成对应的代理类工厂通过Mapper接口获取同包同名的xml文件,并解析Mapper接口通过jdk代理创建代理类,接口方法匹配xml中标签的id值,执行增删改查。

从基础到源码解析的学习记录 3124

Windows 11“此应用已被管理员阻止运行”解决方案

通过本文介绍的两种方法,你应该能够解决Windows 11中“此应用已被管理员阻止运行”的问题。无论你选择创建新管理员账户还是禁用管理员批准模式,都请确保了解相关操作的风险,并根据你的实际需求做出选择。通过禁用“用户账户控制:以管理员批准模式运行所有管理员”设置,可以解决因系统安全设置导致的应用程序被阻止运行的问题。这种方法适用于那些希望简化管理员账户操作流程的用户,但需要注意可能带来的安全风险。通过创建并登录具有管理员权限的新账户,可以解决因系统安全设置导致的应用程序被阻止运行的问题。

mmoo_python的博客 1万+

用 OP-TEE 给 AI 模型“上锁”:密文存储、TEE 解密放行、推理后销毁(实战可落地)

本文提出一种基于OP-TEE的AI模型保护方案,通过两级密钥体系确保模型静态存储为密文,运行时仅在TEE内解密。方案采用KEK+DEK架构,DEK永不出TEE,支持分块解密与可验证擦除。该方案能有效防御静态分析、应用层逆向等威胁,但需承认其物理级攻击的局限性。文章详细描述了端到端架构、文件格式设计及TA实现要点,包括密钥管理、分块解密策略和销毁机制,为设备侧AI部署提供了工程可行的安全解决方案。

Interview_TC的博客 288

MyBatis实现自动代理详解

开发者需要编写Mapper接口,该接口用于定义数据库操作方法。这些方法对应着数据库的增删改查操作,通常以Java方法的形式定义,不需要实现方法体。

weixin_62079735的博客 1804

定位精度再突破!Inner-MPDIoU让YOLOv11边界框回归更精准

Inner-MPDIoU 凭借辅助边框与最小点距离的双机制创新,彻底解决了传统 IoU 损失在边界框回归上的精度瓶颈。本教程从原理到代码实现,再到工业场景适配,完整呈现了其在 YOLOv11 中的集成路径。只需简单修改两处核心脚本,你的目标检测模型就能在边界框定位精度上实现跨越式提升——无论是学术研究中的指标突破,还是工业场景下的精细检测需求,Inner-MPDIoU 都能成为你攻克边界框回归难题的利器。现在就动手尝试,让你的检测模型在定位精度上再上一个台阶吧。

FJN110的博客 157

Mybatis框架基础入门(二)--架构简介

mybatis配置 SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。 mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂 由会话工厂创建sq...

Aaron 738

Linux:安装Debian最新10.x操作系统(超详细)

安装Debian最新10.x操作系统安装Debian最新10.x操作系统1.下载Debian镜像2. 镜像安装引导启动页面,选择图形化安装:选择语言、时区,选中后点击continue:选择键盘模式:配置Hostname主机名,设置Root密码创建普通用户名和密码,进入磁盘分区步骤,选择“所有文件放在同一个分区”确认分区信息磁盘配置完,进入软件安装模块:选择源:进入软件包配置,等待配置结束根据需要选择软件包安装3. 安装完成重启后登录使用 安装Debian最新10.x操作系统 1.下载Debian镜像 下载D

HowieXue 薛永浩的博客 3万+

【MATLAB代码】基于水声通信(ACOMMS)下的到达时间差(TDOA)定位的AUV自主导航例程,附完整代码

水下AUV导航系统仿真研究 本研究基于到达时间差(TDOA)技术实现了水下自主航行器(AUV)的三维导航仿真系统。系统采用四个声学信标作为定位基准,通过TDOA测量数据迭代求解AUV位置。仿真结果表明: 导航性能:系统能够有效跟踪AUV从起点(30,30,-20)到目标点(70,70,-20)的航行轨迹,定位误差保持在合理范围内。 误差分析:定位误差变化曲线显示系统具有稳定的定位精度,平均误差为0.5米左右。 技术特点:采用两步最小二乘迭代算法求解非线性TDOA方程,提高了定位精度和计算效率。 该仿真系统为

985工科博士毕业,专攻定位、导航和滤波等算法研究。从业10年,主要使用MATLAB 320

搞懂MyBatis中设计模式源码——代理模式

无代理不框架,无反射不框架; 万字长文,助你理解MyBatis中动态代理源码

shang_0122的博客 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【面试精讲】MyBatis设计模式及源码分析,MyBatis设计模式实现原理

每个设计模式的实现都体现了MyBatis设计的巧妙和优雅,通过这些模式的应用,MyBatis成功地将框架的灵活性、可扩展性和维护性提升到了一个新的高度。希望通过这三部分的解析,你能对MyBatis的设计和实现有一个更加深入的理解。

小明的Java问道之路 12万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java-19 深入浅出MyBatis 代理模式:从 Java 动态代理到 Mapper 接口的底层原理

代理模式(Proxy Pattern)是 Java 后端最重要的对象结构型设计模式之一,核心思想是"不直接访问真实对象,而是通过代理对象间接访问真实对象",在调用转发前后统一处理日志、权限、事务、缓存、远程调用、延迟加载等横切逻辑。Java 平台提供两套主要代理实现:一是编译期手写的静态代理,简单直观但扩展性差;二是基于 `java.lang.reflect.Proxy` 与 `java.lang.reflect.InvocationHandler` 的 JDK 动态代理,可在运行时按接口动态生成代理类,S

谢谢你的喜欢 我们一起无限进步 3022

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Mybatis框架之代理模式 (Proxy Pattern)

MyBatis 框架中大量使用了代理模式 (Proxy Pattern),尤其在 Mapper 接口 的实现上。代理模式使得 MyBatis 能够在不直接实现接口的情况下动态地提供接口的实现,从而简化数据库操作代码,同时提供更强大的功能。下面将详细解读 MyBatis 中的代理模式的工作原理及其实现。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 1242

理解代理模式,MyBatis原理就掌握了一半

以下文章来源于公众号“程序员求职之路” 在java程序员的世界里,最熟悉的开源软件除了 Spring,Tomcat,还有谁呢? 当然是 Mybatis 了。 MyBatis 是一个被广泛应用的持久化框架。代理模式可以认为是Mybatis的核心使用的模式。 本文通过代理模式,带你掌握MyBatis原理。 ​代理模式含义是为其他的对象提供一种代理以难以控制对这个对象的访问,简而言之即如果有一些我们不能做不想做的事情,可以委托别人去做。 优点是可以不用修改源代码。 代理模式的角色分类有抽象主题(接口)、具体主题

Youz_的博客 561

代理模式的实际运用--(以mybatis拦截器实现原理为例)

之前在写mybatis拦截器的时候,因为不懂原理,琢磨了很久,不知道怎么写,在网上找了很多资料,才知道mybatis的拦截器主要还是通过代理实现的,而且我在之前的博文中刚好学习了代理模式。更精细的是,在mybatis对代理的应用上,不管是封装易用性,减少代码耦合度上,都可以让我之前写的代理模式demo进一步改进,也让我加深了对代理模式的理解。 静态代理需要自己写代理类,比较麻烦,代理的东西一多就很不方便,动态代理只要简单的实现InvocationHandler接口,让jvm自己在运行时生成所需的代理类.

大叶子不小的博客 447

【MyBatis 源码拆解系列】MyBatis 运行原理 - MyBatis 中的代理模式

欢迎关注公众号,持续在我后台回复 「资料」 可领取编程高频电子书!在我后台回复「面试」可领取硬核面试笔记!

qq_45260619的博客 889

[ORM] MyBatis 中是如何运用的代理模式的?

[ORM] MyBatis 中是如何运用的代理模式的? 简介 本文主要介绍设计模式之代理模式,并分析代理模式在 Mybatis 中是如何使用的? 文章目录[ORM] MyBatis 中是如何运用的代理模式的?静态代理动态代理源码分析深入动态代理源码小结获取更多 手机用户请横屏获取最佳阅读体验,REFERENCES中是本文参考的链接,如需要链接和更多资源,可以扫码加入『知识星球』(文末)获取长期知识分享服务。 静态代理 具体用户管理实现类 public class UserManagerIm

架构探险之道 800

MyBatis(四)MyBatis插件原理

MyBatis插件原理 MyBatis对开发者非常友好,它通过提供插件机制,让我们可以根据自己的需要去增强MyBatis的功能。其底层是使用了代理模式+责任链模式 MyBatis官方https://mybatis.org/mybatis-3/zh/configuration.html#plugins可以看到MyBatis允许使用插件来拦截的方法调用 Executor (update, qu...

qq_35448165的博客 532

解锁代理模式:代理模式的多面解析与实战

解锁设计模式:代理模式的多面解析与实战

卓越之识论道,平常之识论事,狭隘之识论人 1222

代理模式的实际运用-以mybatis拦截器实现原理为例

之前在写mybatis拦截器的时候,因为不懂原理,琢磨了很久,不知道怎么写,在网上找了很多资料,才知道mybatis的拦截器主要还是通过代理实现的,而且我在之前的博文中刚好学习了代理模式。更精细的是,在mybatis对代理的应用上,不管是封装易用性,减少代码耦合度上,都可以让我之前写的代理模式demo进一步改进,也让我加深了对代理模式的理解。之前代理模式博文地址:http://blog.csdn.n

致橡树 1364

代理模式实战运用(动态代理)

在开发中使用代理模式,可以在不修改原始对象代码的情况下,为其增加新的操作或功能,符合软件设计的开闭原则。代理模式可分为静态代理和动态代理。

1390

mybatis原理解析

mybatis原理解析

qq_43770865的博客 1854

MyBatis动态代理:原理与实现

在当今的软件开发领域,MyBatis 作为一款优秀的持久层框架,其核心知识点之一便是动态代理的实现。想象一下,在一个大型项目中,我们可能需要频繁地与数据库进行交互,而每次交互都需要编写大量的数据库操作代码。这种情况下,动态代理技术便显得尤为重要。动态代理是一种在运行时创建对象实例的技术,它允许我们在不修改原始类代码的情况下,为对象添加额外的功能。在 MyBatis 中,动态代理被广泛应用于 SQL 映射和数据库操作中,极大地简化了数据库交互的复杂性。为什么需要介绍 MyBatis 核心知识点之动态代理实现:

我是Java程序员廖志伟,感谢朋友们的支持! 1394
上一篇: SpringMVC中DispatchServlet是单例还是多例(附源码分析)
下一篇: 第四代编程语言会是什么样子的?
life is ftc
博客等级 码龄9年 19粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值