【MyBatis源码】SqlSession执行Mapper过程

🎮 作者主页:点击
🎁 完整专栏和代码:点击
🏡 博客主页:点击

文章目录

  • Mapper接口的注册过程
  • knownMappers使用 MapperProxyFactory 而不是直接存储代理类原因分析

Mapper接口的注册过程

Mapper接口用于定义执行SQL语句相关的方法,方法名一般和Mapper XML配置文件中<select|update|delete|insert>标签的id属性相同,接口的完全限定名一般对应Mapper XML配置文件的命名空间。

    SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);UserBean res = mapper.selectDataById(1);
  @Select("select * from t_user where id=#{id}")@Result(column = "jsonInfo", property = "jsonInfo", typeHandler = JsonTypeHandler.class)UserBean selectDataById(int id);

在上面的代码中我们通过sqlSession.getMapper(UserMapper.class);就可以执行对应的SQL语句,但是这只是一个接口,我们并没有提供对应的实现类,那么这个是如何实现的呢?
实际上getMapper()方法返回的是一个动态代理对象。MyBatis中通过MapperProxy类实现动态代理。

MyBatis框架在应用启动时会解析所有的Mapper接口,然后调用MapperRegistry对象的addMapper()方法将Mapper接口信息和对应的MapperProxyFactory对象注册到MapperRegistry对象中。

knownMappers使用 MapperProxyFactory 而不是直接存储代理类原因分析

private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);

knownMappers 是一个 Map<Class<?>, MapperProxyFactory<?>> 类型的成员变量,表示的是 Mapper 类型与其对应的 MapperProxyFactory 对象的映射。
在 MyBatis 的启动过程中,当 MyBatis 扫描到一个新的 Mapper 接口时,它会通过 MapperRegistry 的 addMapper() 方法将该接口及其对应的 MapperProxyFactory 对象注册到 knownMappers 中

为什么knownMappers使用 MapperProxyFactory 而不是直接存储代理类呢?
在 MyBatis 中使用 MapperProxyFactory 而不是直接存储代理类,背后的设计原因和原理主要与 灵活性 和 延迟加载(懒加载)有关。以下是为什么选择 MapperProxyFactory 而不是直接存储代理类的几个关键原因:
【1】 代理类的创建开销:如果在 addMapper 时就直接将代理类实例化并存入 knownMappers 中,这意味着每次添加 Mapper 时都会实例化一个代理对象,这在某些情况下是不必要的,尤其是在大规模的应用程序中,可能会增加性能负担。
【2】 懒加载机制:MapperProxyFactory 作为一个工厂类,它只会在调用 getMapper() 时,针对某个特定的 Mapper接口动态创建代理实例。这样,代理对象只会在需要时创建,避免了在启动时就为每个 Mapper 创建一个代理对象的开销。
【3】 设计原理:这种懒加载的设计方式使得 MyBatis 更加高效。只有在需要对某个 Mapper 进行操作时,才会创建相应的代理对象,避免了不必要的对象创建和内存占用。
【4】 代理类与接口分离:MapperProxyFactory 是一个工厂类,负责根据 Mapper 接口创建代理对象。通过工厂模式,MyBatis 可以灵活地控制何时创建代理类,并且保持代码的解耦性。如果直接存储代理实例,则每次获取时只能使用已创建的代理,无法实现这种灵活的控制。
【5】 工厂模式的好处:使用工厂模式可以让我们在运行时动态地创建不同类型的代理。例如,在不同的环境下,代理对象可能具有不同的行为,或者在某些情况下需要特殊的处理,MapperProxyFactory 可以灵活地根据这些需求创建代理对象。
【6】 控制代理对象的创建:如果直接将代理对象存储在 knownMappers 中,那么在获取 Mapper 时就无法控制代理的创建和配置。而通过工厂模式,MyBatis 可以在创建代理对象时加入一些额外的逻辑,比如事务处理、拦截器等。
【7】 避免多次创建相同的代理:MapperProxyFactory 是通过 newInstance 方法来创建代理对象的,每次调用 getMapper() 方法时,MapperProxyFactory 都会根据当前的 SqlSession 创建一个新的代理实例。而如果直接将代理对象存储在 knownMappers 中,那么每次访问都会返回相同的代理对象,这可能导致一些问题(如会话状态不一致)。通过每次调用 getMapper 创建新的代理对象,MyBatis 可以确保每个 SqlSession 使用的是独立的代理实例,避免不同的会话之间共享相同的代理对象,从而保持隔离性。
【8】 可扩展性。在 MyBatis 中,代理对象可能会涉及到一些额外的逻辑,比如事务管理、缓存管理、日志记录等。这些逻辑通常通过插件或者拦截器的方式进行处理,而 MapperProxyFactory 可以灵活地插入这些处理逻辑。如果直接将代理对象存入 knownMappers,则无法在代理对象创建时灵活地添加这些额外的功能。如果直接存储代理对象,意味着所有的代理类都会被硬编码在 MapperRegistry 中,这不利于框架的灵活扩展。而通过 MapperProxyFactory,MyBatis 可以根据不同的需求创建不同的代理,保持系统的灵活性和可扩展性。
【9】 工厂模式统一管理代理类的创建:MapperProxyFactory 作为一个工厂类,它为每个 Mapper 类型提供了统一的创建代理对象的接口。通过这种方式,MyBatis 可以更清晰地管理不同 Mapper 接口的代理对象,而不需要为每个接口单独处理创建逻辑。

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

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

相关文章

探索 HTML 和 CSS 实现的 3D旋转相册

效果演示 这段HTML与CSS代码创建了一个包含10张卡片的3D旋转效果&#xff0c;每张卡片都有自己的边框颜色和图片。通过CSS的3D变换和动画&#xff0c;实现了一个动态的旋转展示效果 HTML <div class"wrapper"><div class"inner" style"-…

小程序23-页面的跳转:navigation 组件详解

小程序中&#xff0c;如果需要进行跳转&#xff0c;需要使用 navigation 组件&#xff0c;常用属性&#xff1a; 1.url &#xff1a;当前小程序内的跳转链接 2.open-type&#xff1a;跳转方式 navigate&#xff1a;保留当前页面&#xff0c;跳转应用内的某个页面&#xff0c…

什么是Hadoop

Hadoop 介绍 Hadoop 是由 Apache 开发的开源框架&#xff0c;用于处理分布式环境中的海量数据。Hadoop 使用 Java 编写&#xff0c;通过简单的编程模型允许在集群中进行大规模数据集的存储和计算。它具备高可靠性、容错性和扩展性。 分布式存储&#xff1a;Hadoop 支持跨集群…

逆向攻防世界CTF系列39-debug

逆向攻防世界CTF系列39-debug 查了资料说.NET要用其它调试器&#xff0c;下载了ILSPY和dnSPY ILSPY比较适合静态分析代码最好了&#xff0c;函数名虽然可能乱码不显示&#xff0c;但是单击函数名还是能跟踪的&#xff0c;而dnSPY在动态调试上效果好&#xff0c;它的函数名不仅…

Ceph后端两种存储引擎介绍

Ceph是一个可靠的、自治的、可扩展的分布式存储系统&#xff0c;它支持文件系统存储、块存储、对象存储三种不同类型的存储&#xff0c;以满足多样存储的需求。在Ceph的存储架构中&#xff0c;FileStore和BlueStore是两种重要的后端存储引擎&#xff0c;下面将分别进行详细介绍…

华为开源自研AI框架昇思MindSpore应用案例:人体关键点检测模型Lite-HRNet

如果你对MindSpore感兴趣&#xff0c;可以关注昇思MindSpore社区 一、环境准备 1.进入ModelArts官网 云平台帮助用户快速创建和部署模型&#xff0c;管理全周期AI工作流&#xff0c;选择下面的云平台以开始使用昇思MindSpore&#xff0c;获取安装命令&#xff0c;安装MindSpo…

Cellebrite VS IOS18Rebooting

Cellebrite VS IOS18Rebooting我们想分享一些有关 iOS 18 重启“功能”的信息。在过去一周左右的时间里&#xff0c;人们对 iOS 18 中一项新的未记录功能产生了极大关注&#xff0c;该功能会导致设备在一段时间不活动后重新启动。 这意味着&#xff0c;如果设备在一定时间不活…

GNU/Linux - tar命令

1&#xff0c;Online GNU manual tar命令是一个古老的命令&#xff0c;在线帮助手册地址&#xff1a; GNU tar manual - GNU Project - Free Software Foundation GNU tar 1.35 这么一个简单命令&#xff0c;上面的在线手册却是非常的长。 2&#xff0c;Man命令 读取本地的man…

使用 Axios 拦截器优化 HTTP 请求与响应的实践

目录 前言1. Axios 简介与拦截器概念1.1 Axios 的特点1.2 什么是拦截器 2. 请求拦截器的应用与实践2.1 请求拦截器的作用2.2 请求拦截器实现 3. 响应拦截器的应用与实践3.1 响应拦截器的作用3.2 响应拦截器实现 4. 综合实例&#xff1a;一个完整的 Axios 配置5. 使用拦截器的好…

【最大子矩阵——双指针 / 二分】

题目 双指针&#xff1a; 代码 #include <bits/stdc.h> using namespace std; const int N 85, M 1e510; int g[N][M]; int n, m, lim; int ans 1; int main() {ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for(int i 1; i < n; i)for(int …

Java 网络编程概述

网络编程概述 Java是Internet上的语言&#xff0c;它从语言级上提供了对网络应用程序的支持&#xff0c;程序员能够很容易开发常见的网络应用程序。 Java提供了网络类库&#xff0c;可以实现无痛的网络连接&#xff0c;联网的底层细节被隐藏在Java的本机安装系统里&#xff0…

内网渗透-隧道判断-SSH-DNS-icmp-smb-上线linux-mac

1.通道判断 #SMB 隧道&通讯&上线 判断&#xff1a;445 通讯 上线&#xff1a;借助通讯后绑定上线 通讯&#xff1a;直接 SMB 协议通讯即可 #ICMP 隧道&通讯&上线 判断&#xff1a;ping 命令 上线&#xff1a;见前面课程 通讯&#xff1a;其他项…

【优选算法篇】分治乾坤,万物归一:在重组中窥见无声的秩序

文章目录 分治专题&#xff08;二&#xff09;&#xff1a;归并排序的核心思想与进阶应用前言、第二章&#xff1a;归并排序的应用与延展2.1 归并排序&#xff08;medium&#xff09;解法&#xff08;归并排序&#xff09;C 代码实现易错点提示时间复杂度和空间复杂度 2.2 数组…

【微软:多模态基础模型】(3)视觉生成

欢迎关注【youcans的AGI学习笔记】原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微软&#xff1a;多模态基础模型】&#xff08;3&#xff09;视觉生成 【微…

netcore Kafka

一、新建项目KafakDemo <ItemGroup><PackageReference Include"Confluent.Kafka" Version"2.6.0" /></ItemGroup> 二、Program.cs using Confluent.Kafka; using System; using System.Threading; using System.Threading.Tasks;names…

什么是C++内联函数,它的作用是什么?以及和宏定义的区别

内联函数定义 内联函数是在 C 中定义的一种特殊类型的函数。通过使用 inline 关键字&#xff0c;请求编译器在每个调用点直接插入函数体的代码&#xff0c;没有函数压栈&#xff08;函数压栈&#xff1a;在函数调用的时候将函数的相关信息和局部变量等数据储存在栈上的过程&am…

工业生产安全-安全帽第一篇-opencv及java开发环境搭建

一.背景 公司是非煤采矿业&#xff0c;核心业务是采选&#xff0c;大型设备多&#xff0c;安全风险因素多。当下政府重视安全&#xff0c;头部技术企业的安全解决方案先进但价格不低&#xff0c;作为民营企业对安全投入的成本很敏感。利用我本身所学&#xff0c;准备搭建公司的…

详细的oracle rac维护命令集合

一、查看命令 所有实例和服务的状态 $srvctl status database -d orcl Instance orcl1 is running on node db1 Instance orcl2 is running on node db2 单个实例的状态 $ srvctl status instance -d orcl -i orcl2 Instance orcl2 is running on node db2 单个节点的应用程序…

fastadmin多个表crud连表操作步骤

1、crud命令 php think crud -t xq_user_credential -u 1 -c credential -i voucher_type,nickname,user_id,voucher_url,status,time --forcetrue2、修改控制器controller文件 <?phpnamespace app\admin\controller;use app\common\controller\Backend;/*** 凭证信息…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-26

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…