【简写Mybatis-02】注册机的实现以及SqlSession处理
前言
注意:
学习源码一定一定不要太关注代码的编写,而是注意代码实现思想:
通过设问方式来体现代码中的思想;方法:5W+1H
源代码: https://gitee.com/xbhog/mybatis-xbhog ; https://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);
}
目的
- 根据包路径实现接口的扫描和注册
- 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
项目类图
根据包路径实现接口的扫描和注册
可以通过自定义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;
}
@Override
public <T> T selectOne(String statement,Object parameter) {
return (T) ("你被代理了!" + "方法:" + statement + " 入参:" + parameter);
}
@Override
public <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);
}
}
到这里其实已经可以满足需求了,但是看了下源码发现还是不行,它最外层又封装了一层代理工厂;应该是为了后续的代码扩展,简单工厂模式有助于代码的模块性和可维护性,功能上后续会有配置管理、资源管理、执行器选择和插件等需求;走一步看三步的老狐狸(┬┬﹏┬┬)。先抄作业。
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;
}
@Override
public 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);
}
}
总结
- What(什么) :
- MapperRegistry是一个注册表,用于存储映射器接口(Mapper Interface)和对应的MapperProxyFactory。它负责管理映射器接口的生命周期。
- DefaultSqlSessionFactory是MyBatis框架中用于创建SqlSession的工厂类。SqlSession是MyBatis的核心接口,用于执行SQL命令和获取映射结果。
- Why(为什么) :
- MapperRegistry的存在是为了确保映射器接口能够被MyBatis框架识别和管理,以便在运行时为这些接口创建代理对象,实现数据库操作的动态绑定。
- DefaultSqlSessionFactory的目的是为了提供一个统一的入口点,用于创建和管理SqlSession实例。这样可以保证SqlSession的创建和关闭遵循统一的规范,同时提供了会话管理的能力。
- Who(谁) :
- MapperRegistry的使用者是MyBatis框架自身,它内部使用MapperRegistry来处理映射器接口的注册和代理对象的创建。
- DefaultSqlSessionFactory的使用者是应用程序的开发者,他们通过SqlSessionFactory来获取SqlSession实例,进而执行数据库操作。
- Where(在哪里) :
- MapperRegistry是MyBatis框架的一部分,通常在MyBatis配置初始化时创建,并在整个应用程序的生命周期中存在。
- DefaultSqlSessionFactory通常在应用程序启动时创建,并保存在一个全局的变量中,以便在需要时获取SqlSession实例。
- When(何时) :
- MapperRegistry的注册发生在MyBatis应用程序启动时,特别是在构建SqlSessionFactory的过程中。
- DefaultSqlSessionFactory的创建也是在应用程序启动时,通常是在初始化阶段,用于后续的数据库操作。
- How(如何) :
- MapperRegistry通过扫描指定包下的映射器接口,并将它们与对应的MapperProxyFactory关联起来。当需要执行映射器接口中的方法时,MapperRegistry会使用MapperProxyFactory来创建一个MapperProxy代理对象。
- DefaultSqlSessionFactory通过解析MyBatis的配置文件(如mybatis-config.xml,下一节的操作)来创建。它提供了openSession()方法,用于创建SqlSession实例。开发者可以通过SqlSession实例来执行映射器接口中定义的数据库操作。
需要注意的是:通过这两节可以看到mybatis中运用了大量的工厂模式;对外提供统一的方法,屏蔽细节以及上下文的关联关系,最终目的服务于用户,简化使用。
参考
https://mp.weixin.qq.com/s/o6lnWJqU_6FNO8HpxAs9gA
ChatGPT问答
【简写Mybatis-02】注册机的实现以及SqlSession处理的更多相关文章
- BurpSuite 1.7.32 Cracked 破解版[注册机]下载【无后门版】
首先看一下我的注册后的: 注册机的使用也很简单,首先打开burp-loader-keygen.jar文件,然后随便填写license text,比如我填写的是:mrxn.net效果如下图: 然后点击m ...
- PostSharp 4.0注册机实现过程
PostSharp是基于.NET平台设计的比较强调易学易用的AOP框架. 什么是AOP? http://wayfarer.cnblogs.com/articles/241024.html 新版的已失效 ...
- Webstorm 10 for mac osx 注册机,序列号,kegen
小菜最近get到mac体验机会,早就耳闻mac非常适合做开发,于是迫不及待的安装各种开发工具,不知不觉,轮到前端开发神器webstorm了,看了一下官网的价格,心拔凉拔凉的. 果断搜索注册机,搜到的结 ...
- Flash Builder 4.7 注册机完美激活方法
Flash Builder 4.7 破解注册方法目前较为通用的三种方法: 第一种:三步修改配置文件方法,这种有开发者反应这种方法在升级和创建纯 AS 项目时会存在问题,但我懒的去试这种方法的主要原因是 ...
- 转:Autodesk 2017软件下载+注册机+破解方法(持续更新)
转载自http://blog.sina.com.cn/s/blog_710225790102w03e.html Autodesk 2017安装步骤: 安装Autodesk 2017相关软件 使用序列号 ...
- UltraEdit 注册机使用说明
请断开网络连接(或直接拔掉网线)后执行: 安装完成后,点击弹出界面的“注册”按钮,然后直接点击“激活”,此时UltraEdit检测到网络断开则弹出界面提示“脱机激活”,此时启动注册机,并将UltraE ...
- 【转】破解Source Insight 3.5.0072过程 附:安装软件+注册机
转载地址:http://blog.csdn.net/qs_hud/article/details/8884867 注册机及软件下载地址:http://download.csdn.net/detail/ ...
- HTTP抓包神器HTTP Analyzer V7 Build7.5.4汉化+注册机
原版安装包.汉化文件.注册机下载:http://pan.baidu.com/s/1bMv1Si 密码:cqq1 一.安装:下载并安装英文原版 下载页面:http://www.ieinspector. ...
- ERWin 7.2下载安装及注册机
ERWin 7.2下载安装及注册机 ERWin 7.2 下载地址: ftp://ftp.ca.com/CAproducts/erwin/ServicePacks/AFEDM72-b1644.exe ...
- C#:注册机的实现【提供源代码下载】
代码下载 C#软件注册机 软件运行结果 参考文章 http://www.cnblogs.com/hanzhaoxin/archive/2013/01/04/2844191.html
随机推荐
- 力扣8(java)-字符串转整数(atoi)(中等)
题目: 请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数). 函数 myAtoi(string s) 的算法 ...
- 如何落地云原生DevOps?
简介: 什么是云原生DevOps?在阿里内部有怎样的实践?企业又该如何落地?阿里云云效专家团队提出了下一代精益产品开发方法体系--ALPD,提供了系统的云原生DevOps落地的方法支撑,帮助企业渐进式 ...
- 基于 Flutter 的 Web 渲染引擎「北海」正式开源!
简介: 阿里巴巴历时 3 年自研开发的 Web 渲染引擎北海(英文名:Kraken)正式开源,致力打造易扩展,跨平台,高性能的渲染引擎,并已在优酷.大麦.天猫等业务场景中使用. 作者 | 染陌来源 | ...
- 块存储监控与服务压测调优利器-EBS Lens发布
简介:SLS团队联合EBS团队发布了EBS Lens,针对块存储提供数据分析.资源监控的功能,可以帮助用户获取云上块存储资源信息与性能监控数据.提升云上块存储资源的管理效率.高效分析业务波动与资源性 ...
- Flink on Zeppelin 流计算处理最佳实践
简介: 欢迎钉钉扫描文章底部二维码进入 EMR Studio 用户交流群 直接和讲师交流讨论~ 点击以下链接直接观看直播回放:https://developer.aliyun.com/live/247 ...
- .NET周刊【4月第2期 2024-04-21】
国内文章 他来了他来了,.net开源智能家居之苹果HomeKit的c#原生sdk[Homekit.Net]1.0.0发布,快来打造你的私人智能家居吧 https://www.cnblogs.com/h ...
- [GPT] golang代码组织的核心思想
1/golang代码组织的核心思想 Go语言(Golang)在代码组织上的核心思想是模块化和封装,主要体现在以下几个方面: 1.包(Packages): Go语言通过包(Packages)来组织代码, ...
- [ML] 详解 ChatGLM-webui 的启动使用与 ChatGLM-6B 常见问题
1. ChatGLM-webui 总共支持以下几个命令选项: 2. 以 windows 为例,在 PowerShell 里运行命令: # 安装依赖 pip install torch==1.13. ...
- K8s控制器---Statefulset(11)
一.Statefulset概述 1.1 Statefulset控制器:概念和原理解读 StatefulSet 是为了管理有状态服务的问题而设计的 扩展: 有状态服务? StatefulSet 是有状态 ...
- 火山引擎VeDI:如何高效使用A/B实验,优化APP推荐系统
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 在移动互联网飞速发展的时代,用户规模和网络信息量呈现出爆炸式增长,信息过载加大了用户选择的难度,这样的背景下,推荐 ...