【简写MyBatis】01-简单映射器
前言
新开一个坑,为了学习一下MyBatis的源码,写代码是次要的,主要为了吸收一下其中的思想和手法。
目的
关联对象接口和映射类的问题,把 DAO 接口使用代理类,包装映射操作。
知识点
- 动态代理
- 简单工厂模式
InvocationHandler接口的使用
实现
既然是简易的MyBatis编写,那肯定得看下源码了;先来一波回忆,MyBatis的使用:
忘记的朋友可以看下之前写的MyBatis手册: https://blog.csdn.net/weixin_43908900/article/details/129780085
https://www.cnblogs.com/xbhog/p/17258782.html
@Test
public void testMybatis(){
//加载核心配置文件
try {
//字符流加载配置
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建sql连接工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建session连接,设置true,默认提交事务
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//反射获取类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userAll = mapper.getUserAll();
System.out.println(userAll);
} catch (IOException e) {
e.printStackTrace();
}
}
代码中可以看到,接口和映射器有关系的地方应该是sqlSession.getMapper(UserMapper.class);点进去。
先看映射器工厂类:MapperProxyFactory
这部分就是我们本次实现的地方。
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethodInvoker> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
简易映射器类图:
MapperProxy代理类来代理需要使用的接口,为了方便后续的维护扩展,在代理类上加一层代理工厂类MapperProxyFactory
使用代理类的好处是: 动态代理允许 MyBatis 在不修改接口实现的情况下,为接口方法提供自定义的行为。这意味着开发者只需要定义接口和 SQL 映射,而无需编写接口的实现类。这种设计促进了关注点分离,使得数据访问逻辑(SQL)与业务逻辑更加清晰,MapperProxy 能够在运行时将 SQL 语句与接口方法动态绑定,这样,MyBatis 可以根据接口方法的签名和注解或 XML 配置来执行相应的 SQL 操作。
使用简单工厂模式的好处: 实现代码复用和模块化,对代理逻辑和接口使用解耦,灵活性高,不改变公共接口等。
总之都是为了项目的高度灵活、扩展、复用等。
通过上述的分析,现在进行代码编写的流程比较明朗了。
代理类的实现:
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
//模拟SqlSession
private Map<String, String> sqlSession;
private final Class<T> mapperInterface;
public MapperProxy(Map<String, String> sqlSession, Class<T> mapperInterface) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//检查一个方法是否来自特定的类或者是一系列接口中的一个
//是Object自身的方法,就没必要代理,直接调用就行
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
//需要匹配的是类名+方法名
return "你的被代理了!" + sqlSession.get(mapperInterface.getName() + "." + method.getName());
}
}
}
映射器代理工厂实现:
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T newInstance(Map<String, String> sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
}
执行流程如下:
测试
public void testApp() {
MapperProxyFactory<IUserDao> proxyFactory = new MapperProxyFactory<>(IUserDao.class);
Map<String,String> sqlSession = new HashMap<>();
sqlSession.put("com.xbhog.IUserDao.getUserName","模拟执行 Mapper.xml 中 SQL 语句的操作:查询用户姓名");
IUserDao userDao = proxyFactory.newInstance(sqlSession);
String userName = userDao.getUserName("100001");
System.out.println(userName);
}
总结
- 通过追溯
MyBatis中的源码,明确本文的主要的内容 - 明确目标类的依赖关系
- 代码实现简易效果
- 明确执行流程
- 测试代码,符合预期结果
参考&学习
https://mp.weixin.qq.com/s/G3fZES2FvNQK8JLnd9Hx9w
AI大模型辅助
MyBatis源码
【简写MyBatis】01-简单映射器的更多相关文章
- MyBatis实战之映射器
映射器是MyBatis最强大的工具,也是我们使用MyBatis时用得最多的工具,因此熟练掌握它十分必要.MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返 ...
- Java Persistence with MyBatis 3(中文版) 第三章 使用XML配置SQL映射器
关系型数据库和SQL是经受时间考验和验证的数据存储机制.和其他的ORM 框架如Hibernate不同,MyBatis鼓励开发者可以直接使用数据库,而不是将其对开发者隐藏,因为这样可以充分发挥数据库服务 ...
- 【长文】Spring学习笔记(七):Mybatis映射器+动态SQL
1 概述 本文主要讲述了如何使用MyBatis中的映射器以及动态SQL的配置. 2 MyBatis配置文件概览 MyBatis配置文件主要属性如下: <settings>:相关设置,键值对 ...
- 第六章 mybatis注入映射器
为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象 (DAO)的代码,MyBatis-Spring 提供了一个动态代理的实现:Map ...
- SpringMVC中注解和非注解方式下的映射器和适配器总结
1. 非注解方式 1.1 处理器适配器 上一节中使用的处理器适配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapte ...
- java-mybaits-010-mybatis-spring-使用 SqlSession、注入映射器
一. SqlSession概述 在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession.一旦你获得一个 session 之后,你可以使用它来执行映射语句, ...
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
从上一篇的springmvc入门中已经看到,springmvc.xml中的配置了映射器和适配器,是使用非注解的方式来配置的,这是非注解方式的一种,这里再复习一下: 1. 非注解方式 1.1 处理器适配 ...
- MyBatis映射器元素
映射器是MyBatis最强大的工具,也是我们使用MyBatis时用的最多的工具,映射器中主要有增删改查四大元素,来满足不同场景的需要: 下面是主要元素的介绍: select:查询语句 ...
- mybatis映射器配置细则
前面三篇博客我们已经多次涉及到映射器的使用了,增删查基本上都用过一遍了,但是之前我们只是介绍了基本用法,实际上mybatis中映射器可以配置的地方还是非常多,今天我们就先来看看映射器还有哪些需要配置的 ...
- MyBatis中映射器Mapper概述
MyBatis真正强大之处在于它的映射器.因为它异常强大并且编写相对简单,不仅比传统编写SQL语句做的更好并且能节省将近95%的代码量 XML中顶级元素汇总 cache: 给定命名空间的缓存配置 ca ...
随机推荐
- langchain中的Document类
在Langchain-Chatchat的上传文档接口(upload_docs)中有个自定义的docs字段,用到了Document类.根据发现指的是from langchain.docstore.d ...
- 基于Java 的商城网站系统设计与实现(8000字论文)
摘要 随着我国经济活力的不断提升和互联网的快速发展,信息的重要性正在显现出来.电子商务作为经济发展的重要一环取得了突飞猛进的发展.由于具有高效便捷的优点,网上购物已经成为一种不可或缺的新型生活方式,近 ...
- k8s~istio的安装与核心组件
安装istio 在线安装:https://istio.io/latest/docs/setup/getting-started/#download 或者直接在这里下载:https://github.c ...
- [转帖]解Bug之路-NAT引发的性能瓶颈
https://zhuanlan.zhihu.com/p/286532997 解Bug之路-NAT引发的性能瓶颈 笔者最近解决了一个非常曲折的问题,从抓包开始一路排查到不同内核版本间的细微差异,最后才 ...
- [转帖]nginx 剖析 request_time和upstream_response_time的误区、区别
https://cloud.tencent.com/developer/article/1767981 首先,澄清一个误区 upstream_response_time必须在upstream配置时才能 ...
- [转帖]Oracle 创建和查看DBLink 的方法
https://www.cnblogs.com/zhouzangood/articles/4612441.html 1.如果需要创建全局 DBLink,则需要先确定用户有创建 dblink 的权限: ...
- [转帖]实用小技能:一键获取Harbor中镜像信息,快捷查询镜像
[摘要]一键获取Harbor中的镜像列表,无需登录harbor UI,也可批量下载镜像到本地并保存为tar包.本文已参与「开源摘星计划」,欢迎正在阅读的你加入.活动链接:https://github. ...
- [转帖]PCIe信息查询
https://www.jianshu.com/p/b3a57fcaff8d 查询PCIe设备厂商信息 通过PCIe设备的描述信息进行查询 PCIe设备的描述:Class号.厂商号(vender id ...
- 龙芯中标麒麟 上面安装libgdiplus的方法
其实方法与之前的blog 基本上完全一样 但是发现有一个问题 安装完libgdiplus之后必须重启一下才能有效果... CentOS 安装libgdi的方法 1. 安装必须的包 1 yum ins ...
- Linux KVM网络处理过程
Linux KVM网络处理过程 总体解决方法 本次遇到的问题是KVM的网桥处理不小心导致系统无法连接.处理简要总结: 进入机房,给IPMI插上网线, 开机点 Del 进入bios 设置IMPI的地址 ...