手撸Mybatis(一)——代理mapper

引言

最近刚写完毕设,闲来无事,看到网上有一个手撸Mybatis的教程,于是想自己实现一个简易版的Mybatis。
本专栏的源码:https://gitee.com/dhi-chen-xiaoyang/yang-mybatis。

创建简单的映射器代理工厂

在使用mybatis的时候,我们一般只需要定义mapper的接口,并添加相应的@Mapper注解,然后实现对应的xml文件即可,而不需要对mapper接口进行具体的实现。其实本质上,这些mapper接口是有实现的,但不是我们手动通过implement来实现,而是通过代理的方式进行实现。因此,对于Mybatis的手撸,首先要关注的,就是如何对mapper进行代理。
首先我们定义一个MapperProxy,该类实现InvocationHandler接口,通过实现该接口,实现动态代理。这里有两个属性——sqlSession和mapperInterface,其中,sqlSession是用来模拟执行sql语句的。

package com.yang.mybatis.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;public class MapperProxy<T> implements InvocationHandler {private Map<String, Object> sqlSession ;private Class<T> mapperInterface;public MapperProxy(Map<String, Object> sqlSession, Class<T> mapperInterface) {this.sqlSession = sqlSession;this.mapperInterface = mapperInterface;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);}String key = this.mapperInterface.getName() + "." + method.getName();return sqlSession.get(key);}
}

当我们在执行mapper的某个方法时,最终会进入到invoke方法,并通过sqlSession来获取模拟值。
接着我们定义MapperProxyFactory,每一个mapper都有一个MapperProxyFactory与之相对应,然后newInstance方法接收模拟的sql结果,并通过Proxy.newProxyInstance创建动态代理对象。

package com.yang.mybatis.proxy;import java.lang.reflect.Proxy;
import java.util.Map;public class MapperProxyFactory <T> {private final Class<T> mapperInterface;public MapperProxyFactory(Class<T> mapperInterface) {this.mapperInterface = mapperInterface;}public T newInstance(Map<String, Object> sqlSession) {MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),new Class[]{mapperInterface},mapperProxy);}
}

最后,我们先创建一个IUserMapper类

package com.yang.mybatis.test;public interface IUserMapper {String queryUserName(Integer id);Integer queryUserAge(Integer id);
}

然后创建对应的测试方法

package com.yang.mybatis.test;import com.yang.mybatis.proxy.MapperProxyFactory;import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) {MapperProxyFactory<IUserMapper> userDaoMapperProxyFactory = new MapperProxyFactory<>(IUserMapper.class);Map<String, Object> sqlSession = new HashMap<>();sqlSession.put("com.yang.mybatis.test.IUserMapper.queryUserName", "模拟查询用户名");sqlSession.put("com.yang.mybatis.test.IUserMapper.queryUserAge", 1);IUserMapper iUserMapper = userDaoMapperProxyFactory.newInstance(sqlSession);System.out.println(iUserMapper.queryUserAge(1));System.out.println(iUserMapper.queryUserName(1));}
}

运行结果如下:
image.png

实现映射器的注册和使用

像上述的这种方法,我们每次要获取一个Mapper,就要new一个对应的MapperProxyFactory,这样不太方便。一般情况下,mapper是放在同一个包下的,那么我们可以通过扫描包,来初始化MapperProxyFactory。至于上一节的sqlSession,因为我们目前是模拟数据,所以在初始化过程中,把这些模拟数据要随便mock住就行。
因为要扫描包获取包下的Class类,我们先添加hutool-all,以便通过其提供的ClassScanner获取包

   <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version></dependency>

然后,我们修改MapperProxyFactory

package com.yang.mybatis.proxy;import cn.hutool.core.lang.ClassScanner;import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapperProxyFactory {private Map<Class, MapperProxy> mapperProxyMap = new HashMap<>();public MapperProxyFactory(String packageName) {// 扫描包ClassScanner scanner = new ClassScanner(packageName);Set<Class<?>> mapperTypes = scanner.scan();for (Class<?> mapperType : mapperTypes) {if (!mapperType.isInterface()) {// 只对接口进行处理continue;}Map<String, String> mockSqlSession = mockSqlSession(mapperType);MapperProxy mapperProxy = new MapperProxy(mockSqlSession, mapperType);mapperProxyMap.put(mapperType, mapperProxy);}}public Object newInstance(Class mapperType) {MapperProxy mapperProxy = mapperProxyMap.get(mapperType);return Proxy.newProxyInstance(mapperType.getClassLoader(),new Class[]{mapperType},mapperProxy);}private Map<String, String> mockSqlSession(Class mapperType) {Map<String, String> sqlSession = new HashMap<>();for (Method method : mapperType.getMethods()) {String methodName = method.getName();String key = mapperType.getName() + "." + methodName;sqlSession.put(key, key);}return sqlSession;}
}

最后进行测试:

  public static void main(String[] args) {MapperProxyFactory mapperProxyFactory = new MapperProxyFactory("com.yang.mybatis.test");IUserMapper iUserMapper = (IUserMapper) mapperProxyFactory.newInstance(IUserMapper.class);System.out.println(iUserMapper.queryUserName(1));}

测试结果如下:
image.png

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

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

相关文章

Python语言在地球科学中地理、气象、气候变化、水文、生态、传感器等数据可视化到常见数据分析方法的使用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台&#xff08;x86和arm&#xff09;&#xff0c;Python简洁的语法和对动态输入的支持&#xff0c;再加上解释性语言的本质&…

doxygen 辅助阅读代码的神器

简介 Doxygen是一个文档生成工具&#xff0c;主要用于编写编程语言的软件文档。它最初是为C设计的&#xff0c;但后来增加了对C、C#、Java、Objective-C、Python、IDL&#xff08;在某些情况下还有PHP、C#和D&#xff09;的支持。Doxygen可以从一组带有文档注释的源代码文件中…

Mamba3D革新3D点云分析:超越Transformer,提升本地特征提取效率与性能!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Mamba3D革新3D点云分析&#xff1a;超越Transformer&#xff0c;提升本地特征提取效率与性能&#xff01; 引言&#xff1a;3D点云分析的重要性与挑战 3D点云…

软件工程毕业设计选题100例

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

ubuntu ros noetic 编译 ORB_SLAM2 过程记录

1. 连接 eigen库 sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen 2. opencvx 修改 CMakeList.txt 中的 find_package open cv版本 修改 include/orbExtracter.h 文件为&#xff1a; //#include <opencv2/opencv.hpp> #include<opencv2/imgproc/imgpro…

【深入浅出MySQL】「性能调优」高性能查询优化MySQL的SQL语句编写

高性能查询优化MySQL的SQL语句编写准则这里写目录标题 总体优化大纲&#xff08;1&#xff09;优化查询性能&#xff1a;通过索引降低全表扫描频率优化方向案例介绍问题分析解决方案建立复合索引建立单独索引 &#xff08;2&#xff09;优化数据表与查询&#xff1a;合理使用非…

【C语言的完结】:最后的测试题

看到这句话的时候证明&#xff1a; 此刻你我都在努力~ 个人主页&#xff1a; Gu Gu Study ​​ 专栏&#xff1a;语言的起点-----C语言 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹…

PZK via OWF

参考文献&#xff1a; [SMP88] Santis A, Micali S, Persiano G. Non-Interactive Zero-Knowledge with Preprocessing[C]//Advances in Cryptology—CRYPTO’88.[LS90] Lapidot D, Shamir A. Publicly verifiable non-interactive zero-knowledge proofs[C]//Advances in Cry…

解决WordPress无法强制转换https问题

原因&#xff1a;我在用cs的时候&#xff0c;突然老鸟校园网突然断了&#xff0c;客户端cs连不上了&#xff0c;进程也杀不死&#xff0c;cpu占用100%&#xff0c;只能重启&#xff0c;但是重启后我的blog网站打不开了 开始以为是Nginx的问题&#xff0c;重启它说配置出了问题…

python学习笔记B-14:序列结构之元组--元组的访问与遍历

下面是几种元组的方位与遍历方法&#xff1a; t ("hello","python","world") print("原元组",t) print("t[1]",t[1]) print("t[0:3:2]",t[0:3:2]) #切片操作&#xff0c;从索引值0到索引值为2&#xff0c;步长为…

利用大语言模型(KIMI)构建智能产品的控制信息模型

数字化的核心是数字化建模&#xff0c;为一个事物构建数字模型是一项十分复杂的工作。不同的应用场景&#xff0c;对事物的关注重点的不同的。例如&#xff0c;对于一个智能传感器而言&#xff0c;从商业的角度看&#xff0c;产品的信息模型中应该包括产品的类型&#xff0c;名…

修改Ubuntu远程登录欢迎提示信息

无论何时登录公司的某些生产系统&#xff0c;你都会看到一些登录消息、警告或关于你已登录服务器的信息&#xff0c;如下所示。 修改方式 1.打开ubuntu终端,进入到/etc/update-motd.d目录下面 可以发现目录中的文件都是shell脚本, 用户登录时服务器会自动加载这个目录中的文件…

ThreeJS:坐标辅助器与轨道控制器

ThreeJS与右手坐标系 使用ThreeJS创建3D场景时&#xff0c;需要使用一个坐标系来定位和控制对象的位置和方向。 ThreeJS使用的坐标系是右手坐标系&#xff0c;即&#xff1a;X轴向右、Y轴向上、Z轴向前&#xff0c;如下图所示&#xff0c; ThreeJS-右手坐标系 Tips&#xff1a;…

【C++】命名冲突了怎么办?命名空间来解决你的烦恼!!!C++不同于C的命名方式——带你认识C++的命名空间

命名空间 导读一、什么是C?二、C的发展三、命名空间3.1 C语言中的重名冲突3.2 什么是命名空间&#xff1f;3.3 命名空间的定义3.4 命名空间的使用环境3.5 ::——作用域限定符3.6 命名空间的使用方法3.6.1 通过作用域限定符来指定作用域3.6.2 通过关键字using和关键字namespace…

云服务器+ASF实现全天挂卡挂时长

目录 前言正文1.安装下载2.编辑配置文件3.设置Steam社区证书4.启动ASF5.给游戏挂时长6.进阶-ASF自动启动且后台保活 前言 我遇到的最大的问题是&#xff0c;网络问题 其实不然&#xff0c;各大厂商的云服务器后台都有流量监控&#xff0c;意味着依靠一般方法是不能正常访问St…

变量内存和存储单位

基本数据类型及其占位符 存储单位 内存中的数据存储单元是由一个一个的二进制组成的&#xff0c;每个二进制只能存储0 和1 科学家为了更加方便存储更多的数据&#xff0c;把内存中8个二进制分为一组&#xff0c;叫做一个字节&#xff0c;Byte字节是最小的存储单位。(重点⭐⭐⭐…

聚焦Spring后置处理器分析对比

目录 一、理解Spring后置处理器 二、Spring后置处理器在IOC容器和bean对象生命周期的切入时机分析 &#xff08;一&#xff09;IOC 容器生命周期中的切入时机 &#xff08;二&#xff09;Bean 对象生命周期中的切入时机 三、BeanPostProcessor后置器分析 &#xff08;一&…

OpenCV(三)—— 车牌筛选

本篇文章要介绍如何对从候选车牌中选出最终进行字符识别的车牌。 无论是通过 Sobel 还是 HSV 计算出的候选车牌都可能不止一个&#xff0c;需要对它们进行评分&#xff0c;选出最终要进行识别的车牌。这个过程中会用到两个理论知识&#xff1a;支持向量机和 HOG 特征。 1、支…

Redis__事务

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a;Redis__事务 ⏱️ 创作时间&#xff1a;2024年05月02日 ———————————————— 这里写目录标题 文章目…

SSM+Vue在线OA办公系统

在线办公分三个用户登录&#xff0c;管理员&#xff0c;经理&#xff0c;员工。 SSM架构&#xff0c;maven管理工具&#xff0c;数据库Mysql&#xff0c;系统有文档&#xff0c;可有偿安装调试及讲解&#xff0c;项目保证质量。需要划到 最底 下可以联系到我。 功能如下&am…