【简写Mybatis】02-注册机的实现以及SqlSession处理

前言

注意:

学习源码一定一定不要太关注代码的编写,而是注意代码实现思想:

通过设问方式来体现代码中的思想;方法:5W+1H

源代码:https://gitee.com/xbhog/mybatis-xbhoghttps://github.com/xbhog/mybatis-xbhog;交个朋友,有价值欢迎star。

回顾&分析

上一局实现Mapper接口和映射器通过代理类的方式进行链接。

上一局测试类:【简写MyBatis】01-简单映射器;虽然基本功能实现了,但是还不智能,可以发现该测试类中的映射器代理工厂只能实现单一的接口代理,SqlSession也需要规范化处理;将映射器代理和方法的调用类似服务进行包装。

@Test
public void test_MapperProxyFactory() {MapperProxyFactory<IUserDao> factory = new MapperProxyFactory<>(IUserDao.class);Map<String, String> sqlSession = new HashMap<>();sqlSession .put("com.xbhog.IUserDao.getUserName","模拟执行 Mapper.xml 中 SQL 语句的操作:查询用户姓名");IUserDao userDao = factory.newInstance(sqlSession);String res = userDao.queryUserName("10001");logger.info("测试结果:{}", res);
}

目的

  1. 根据包路径实现接口的扫描和注册
  2. SqlSession规范化处理

实现

项目结构:

└─src ├─main │ └─java │   └─com │     └─xbhog │       ├─binding │       │ ├─MapperProxy.java │       │ ├─MapperProxyFactory.java │       │ └─MapperRegistry.java │       └─session │         ├─DefaultSqlSession.java │         ├─DefaultSqlSessionFactory.java │         ├─SqlSession.java │         └─SqlSessionFactory.java └─test └─java └─com └─xbhog ├─AppTest.java └─IUserDao.java 

项目类图

img

根据包路径实现接口的扫描和注册

可以通过自定义MapperRegistry这个类实现该功能,当然你也可以叫其他的名字(zhangsan、lisi😅);我们只需要将上一局的MapperProxyFactory封装到MapperRegistry,把需要扫描和注册的接口保存到Map中进行预处理,最后代理进行随时使用就可以了;铺垫结束,开始上代码。

先扫描包下所有的Class类,然后保存到Map中。

package com.xbhog;import cn.hutool.core.lang.ClassScanner;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** @author xbhog* @describe: 接口注册器* @date 2024/2/25*/
public class MapperRegistry {private final Map<Class<?>,MapperProxyFactory<?>> interfaceMaps = new HashMap<>();public void addMapper(String packageName){Set<Class<?>> scanPackage = ClassScanner.scanPackage(packageName);scanPackage.forEach(clazz -> {addMappers(clazz);});}private void addMappers(Class<?> clazz) {if(clazz.isInterface()){//判断是否重复添加if(haveInterface(clazz)){throw new RuntimeException("Type " + clazz + " is already known to the MapperRegistry.");}}// 注册映射器代理工厂interfaceMaps.put(clazz, new MapperProxyFactory<>(clazz));}private boolean haveInterface(Class<?> clazz) {return interfaceMaps.containsKey(clazz);}}

然后将上一局的接口和代理工厂操作封装进方法中。

public <T> T getMapper(Class<T> type, SqlSession sqlSession){MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) interfaceMaps.get(type);if(Objects.isNull(mapperProxyFactory)){throw new RuntimeException("Type " + type + " is not known to the MapperRegistry.");}return (T)mapperProxyFactory.newInstance(sqlSession);
}

SqlSession规范化处理

先定义一个执行Sql、获取映射器的标准接口:

/*** @author xbhog* @describe: 定义简单的Mapper操作方法* @date 2024/2/25*/
public interface SqlSession {<T> T selectOne(String statement,Object parameter);/***得到接口映射器* @param type 接口类型* @return*/<T> T getMapper(Class<T> type);
}

接口实现方式:

package com.xbhog.session;import com.xbhog.binding.MapperRegistry;/*** @author xbhog* @describe:* @date 2024/2/25*/
public class DefaultSqlSession implements SqlSession{private MapperRegistry mapperRegistry;public DefaultSqlSession(MapperRegistry mapperRegistry) {this.mapperRegistry = mapperRegistry;}@Overridepublic <T> T  selectOne(String statement,Object parameter) {return (T) ("你被代理了!" + "方法:" + statement + " 入参:" + parameter);}@Overridepublic <T> T getMapper(Class<T> type) {return mapperRegistry.getMapper(type,this);}
}

测试一下:

package com.xbhog;import com.xbhog.binding.MapperProxyFactory;
import com.xbhog.binding.MapperRegistry;
import com.xbhog.session.DefaultSqlSession;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;import java.util.HashMap;
import java.util.Map;/*** Unit test for simple App.*/
public class AppTest extends TestCase {/*** Rigourous Test :-)*/public void testApp() {MapperRegistry mapperRegistry = new MapperRegistry();mapperRegistry.addMapper("com.xbhog");DefaultSqlSession sqlSession = new DefaultSqlSession(mapperRegistry);IUserDao user = sqlSession.getMapper(IUserDao.class);String userName = user.getUserName("xbhog");System.out.println("输出的信息:"+userName);}
}

img

到这里其实已经可以满足需求了,但是看了下源码发现还是不行,它最外层又封装了一层代理工厂;应该是为了后续的代码扩展,简单工厂模式有助于代码的模块性和可维护性,功能上后续会有配置管理、资源管理、执行器选择和插件等需求;走一步看三步的老狐狸(┬┬﹏┬┬)。先抄作业。

package com.xbhog.session;import com.xbhog.binding.MapperRegistry;/*** @author xbhog* @describe:* @date 2024/2/25*/
public class DefaultSqlSessionFactory implements SqlSessionFactory{private final MapperRegistry mapperRegistry;public DefaultSqlSessionFactory(MapperRegistry mapperRegistry) {this.mapperRegistry = mapperRegistry;}@Overridepublic SqlSession openSession() {return new DefaultSqlSession(mapperRegistry);}
}

测试

package com.xbhog;import com.xbhog.binding.MapperProxyFactory;
import com.xbhog.binding.MapperRegistry;
import com.xbhog.session.DefaultSqlSession;
import com.xbhog.session.DefaultSqlSessionFactory;
import com.xbhog.session.SqlSession;
import com.xbhog.session.SqlSessionFactory;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;import java.util.HashMap;
import java.util.Map;/*** Unit test for simple App.*/
public class AppTest extends TestCase {/*** Rigourous Test :-)*/public void testApp() {MapperRegistry mapperRegistry = new MapperRegistry();mapperRegistry.addMapper("com.xbhog");DefaultSqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory(mapperRegistry);SqlSession sqlSession = sqlSessionFactory.openSession();IUserDao user = sqlSession.getMapper(IUserDao.class);String userName = user.getUserName("xbhog");System.out.println("输出的信息:"+userName);}
}

img

总结

  1. What(什么)
  • MapperRegistry是一个注册表,用于存储映射器接口(Mapper Interface)和对应的MapperProxyFactory。它负责管理映射器接口的生命周期。
  • DefaultSqlSessionFactory是MyBatis框架中用于创建SqlSession的工厂类。SqlSession是MyBatis的核心接口,用于执行SQL命令和获取映射结果。
  1. Why(为什么)
  • MapperRegistry的存在是为了确保映射器接口能够被MyBatis框架识别和管理,以便在运行时为这些接口创建代理对象,实现数据库操作的动态绑定。
  • DefaultSqlSessionFactory的目的是为了提供一个统一的入口点,用于创建和管理SqlSession实例。这样可以保证SqlSession的创建和关闭遵循统一的规范,同时提供了会话管理的能力。
  1. Who(谁)
  • MapperRegistry的使用者是MyBatis框架自身,它内部使用MapperRegistry来处理映射器接口的注册和代理对象的创建。
  • DefaultSqlSessionFactory的使用者是应用程序的开发者,他们通过SqlSessionFactory来获取SqlSession实例,进而执行数据库操作。
  1. Where(在哪里)
  • MapperRegistry是MyBatis框架的一部分,通常在MyBatis配置初始化时创建,并在整个应用程序的生命周期中存在。
  • DefaultSqlSessionFactory通常在应用程序启动时创建,并保存在一个全局的变量中,以便在需要时获取SqlSession实例。
  1. When(何时)
  • MapperRegistry的注册发生在MyBatis应用程序启动时,特别是在构建SqlSessionFactory的过程中。
  • DefaultSqlSessionFactory的创建也是在应用程序启动时,通常是在初始化阶段,用于后续的数据库操作。
  1. How(如何)
  • MapperRegistry通过扫描指定包下的映射器接口,并将它们与对应的MapperProxyFactory关联起来。当需要执行映射器接口中的方法时,MapperRegistry会使用MapperProxyFactory来创建一个MapperProxy代理对象。
  • DefaultSqlSessionFactory通过解析MyBatis的配置文件(如mybatis-config.xml,下一节的操作)来创建。它提供了openSession()方法,用于创建SqlSession实例。开发者可以通过SqlSession实例来执行映射器接口中定义的数据库操作。

需要注意的是:通过这两节可以看到mybatis中运用了大量的工厂模式;对外提供统一的方法,屏蔽细节以及上下文的关联关系,最终目的服务于用户,简化使用。

参考

https://mp.weixin.qq.com/s/o6lnWJqU_6FNO8HpxAs9gA

ChatGPT问答

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

vs+qt实现摄像头开启以及拍照功能

无标题 开启摄像头三步走第一步UI界面&#xff0c;自己画的第二步 定义对象第三步 实现功能 后面还有踩得坑记录一下。。。关于UI对象的定义关于使用摄像头前提准备 开启摄像头三步走 第一步UI界面&#xff0c;自己画的 第二步 定义对象 一个UI 一个摄像头 一个用来显示摄像头…

NUS神经网络生成我感觉解读过于夸大了

网上对其解读有点过了&#xff0c;只是合成了最后标准化层的参数&#xff0c;或者是更多的其他层参数。而不是网络结构。对于新任务下的网络结构以及参数如何生成&#xff0c;应该是做不到的&#xff0c;论文意义有限。 论文片段&#xff1a;我们提出了神经网络扩散&#xff0…

GOLANG开发 - Echo 框架 入门

好久没有更新过了&#xff0c;今年年底特别的忙&#xff0c;不知道为啥&#xff0c;太忙了简直&#xff0c;抽空出来赶紧更新一篇关于golang的文章&#xff0c;本次主将的是即Gin框架和Beego框架之后的有一个框架&#xff0c;叫 Echo框架 学习过PHP的同学肯定对这个词不陌生&am…

2步破解官方sublime4

sublime简要破解流程 1.下载sublime官方最新版2. 破解流程 1.下载sublime官方最新版 打开 官方网站下载 portable version 版&#xff0c;省的安装。。解压到任意位置&#xff0c;备份 sublime_text.exe 文件 2. 破解流程 打开网址把文件 sublime_text.exe 拖入网页搜索替换…

Android之UI Automator框架源码分析(第九篇:UiDevice获取UiAutomation对象的过程分析)

前言 通过UiDevice的构造方法&#xff0c;UiDevice对象持有的几个对象一部分是在构造方法中创建的&#xff08;初始化&#xff09;&#xff0c;它持有的每个对象都是分析的重点 备注&#xff1a;当前对象持有的对象&#xff0c;它的位置一般在实例变量创建时或者构造方法中&…

node14下运行项目报错:regeneratorRuntime is not defined

regeneratorRuntime is not defined&#xff0c;这是由于配置babel出错问题&#xff0c;由于使用了es7语法如async/await而当前babel版本过低 解决&#xff1a; npm install -D babel-plugin-transform-runtime babel-runtime 安装完成后在.babelrc文件下配置&#xff1a; &qu…

矢量图绘制软件:EazyDraw for Mac v11.6.0中文版

EazyDraw是一款功能强大的矢量绘图软件&#xff0c;适用于Mac平台。它提供了直观易用的工具和功能&#xff0c;方便用户进行各种类型的绘图工作&#xff0c;包括插图、图表、技术绘图、流程图、CAD图纸等。 EazyDraw具有丰富的绘图工具&#xff0c;包括线条、多边形、文本、图像…

springboot-基础-eclipse配置+helloword示例

备份笔记。所有代码都是2019年测试通过的&#xff0c;如有问题请自行搜索解决&#xff01; 目录 配置helloword示例新建项目创建文件 配置 spring boot官方有定制版eclipse&#xff0c;也就是STS&#xff0c;因为不想再装&#xff0c;所以考虑eclipse插件安装jdk和eclipse安装…

人脸2D和3D道具SDK解决方案提供商

人脸识别和增强现实技术成为了许多企业和开发者关注的焦点&#xff0c;为了满足市场对高质量、易于集成的人脸识别SDK的需求&#xff0c;美摄科技推出了一系列领先的人脸2D/3D道具SDK解决方案。 一、产品特点 高精度识别&#xff1a;美摄科技的人脸识别技术采用深度学习算法&…

贝叶斯核机器回归拓展R包:bkmrhat

1.摘要 bkmrhat包是用于扩展bkmr包的贝叶斯核机器回归&#xff08;Bayesian Kernel Machine Regression, BKMR&#xff09;分析工具&#xff0c;支持多链推断和诊断。该包利用future, rstan, 和coda包的功能&#xff0c;提供了在贝叶斯半参数广义线性模型下进行identity链接和 …

企业想要高效上云?如何实现?

进入数字化、智能化时代以后&#xff0c;企业数字化转型已成为企业发展的必然趋势。浪潮之中&#xff0c;越来越多的企业开始积极探索上云路径&#xff0c;云上创新已经成为企业加速数字化转型&#xff0c;提升竞争力的必经之路。 赞奇与华为携手共创云桌面SaaS产品—赞奇云工作…

【Flutter/Android】新建项目,打开android 目录,报错红色以及开启 MultiDex 配置

1 报错红色问题。 单独打开 Flutter 项目下的 android 项目即可。 也就是说&#xff0c;你要一部分原生代码开发&#xff0c;你就需要自己把 android 项目单独出去做&#xff08;其实就相当于android 项目引用 Flutter的dart部分&#xff09;。也就是说&#xff0c;在 Flutter…

鲲鹏arm64架构下安装KubeSphere

鲲鹏arm64架构下安装KubeSphere 官方参考文档: https://kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/ 在Kubernetes基础上最小化安装 KubeSphere 前提条件 官方参考文档: https://kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequi…

uniapp的微信小程序授权头像昵称(最新版)

前面我出过两期博客关于小程序授权登录,利用php实现一个简单的小程序授权登录并存储授权用户信息到数据库的完整流程。无奈&#xff0c;小程序官方又整幺蛾子了。wx.getUserInfo接口收回&#xff0c;wx.getUserProfile接口也不让用。导致我的个人小程序&#xff1a;梦缘 的授权…

Unity中URP下实现水体(水面高光)

文章目录 前言一、实现高光反射原理1、原理&#xff1a;2、公式&#xff1a; 二、实现1、定义 _SpecularColor 作为高光反射的颜色2、定义 _SpecularIntensity 作为反射系数&#xff0c;控制高光反射的强度3、定义 _Smoothness 作为高光指数&#xff0c;用于模型高光范围4、模拟…

FL Studio Producer Edition2024中文进阶版Win/Mac

FL Studio Producer Edition&#xff0c;特别是其【中文进阶版 Win/Mac】&#xff0c;是数字音乐制作领域中的一款知名软件。它为广大音乐制作人、声音工程师以及音乐爱好者提供了一个从音乐构思到最终作品发布的完整解决方案。这个版本特别为中文用户优化&#xff0c;并兼容W…

SpringCache缓存专题

SpringCache缓存专题 学习目标 1、理解缓存存在的意义 2、掌握redis与SpringCache的集成方式 3、掌握SpringCache注解的使用 4、掌握项目集成SpringCache流程 第一章 基于SpringCache缓存方案 1.为什么需要缓存 ​ 前台请求&#xff0c;后台先从缓存中取数据&#xff0…

将SU模型导入ARCGIS,并获取高度信息,多面体转SHP文件(ARCMAP)

问题:将Sketchup中导出的su模型,导入arcgis并得到面shp文件,进而获取各建筑的高度、面积等信息。 思路: (1)导入arcgis得到多面体 (2)转为面shp文件 (3)计算高度/面积等 1、【3D Analyst工具】【转换】【由文件转出】【导入3D文件】(在此步骤之间,建议先建立一个…

【Flink精讲】Flink状态及Checkpoint调优

RocksDB大状态调优 RocksDB 是基于 LSM Tree 实现的&#xff08;类似 HBase&#xff09; &#xff0c;写数据都是先缓存到内存中&#xff0c; 所以 RocksDB 的写请求效率比较高。 RocksDB 使用内存结合磁盘的方式来存储数据&#xff0c;每 次获取数据时&#xff0c;先从内存中 …

NVIDIA的RTX 500和1000系列专业Ada世代笔记本GPU,让你随时随地享受AI增强的工作流程

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…