【简写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 ...
随机推荐
- 基于taro搭建小程序多项目框架
前言 为什么需要这样一个框架,以及这个框架带来的好处是什么? 从字面意思上理解:该框架可以用来同时管理多个小程序,并且可以抽离公用组件或业务逻辑供各个小程序使用.当你工作中面临这种同时维护多个小程序的 ...
- Git-基本命令-init-add-commit-status
- STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驱动
1.准备材料 开发板(正点原子stm32f407探索者开发板V2.4) STM32CubeMX软件(Version 6.10.0) 野火DAP仿真器 keil µVision5 IDE(MDK-Arm ...
- [转帖]Django10——从db.sqlite3迁移到MySQL
https://blog.csdn.net/weixin_47197906/article/details/124889477 文章目录 1.查看Django支持的数据库 2.修改数据库配置 1.查看 ...
- [转帖]可直接拿来用的kafka+prometheus+grafana监控告警配置
kafka配置jmx_exporter 点击:https://github.com/prometheus/jmx_exporter,选择下面的jar包下载: 将下载好的这个agent jar包上传到k ...
- [转帖]自动化运维:一键自动化脚本-shell
https://www.cnblogs.com/luoahong/articles/8456203.html shell函数 1.分别在服务器和客户端上创建www用户 1 2 useradd www ...
- JVM 堆外内存查看方法
JVM 堆外内存查看方法 JVM 堆外内存查看方法 1.概述 是否曾经想过为什么Java应用程序通过众所周知的*-Xms和-Xmx调整标志消耗的内存比指定的数量大得多 ?由于各种原因和可能的优化,JV ...
- Jumper Server 堡垒机搭建过程
Jumper Server 堡垒机搭建过程 背景说明 公司组织考核, 要对一套系统进行安全设置.有一个项目是使用堡垒机进行登录 堡垒机有多种用途,可以实现日志审计和安全设置等. 买商业设备的话太困难了 ...
- 任意文件下载包含https的图片
使用a标签进行下载 <a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ. ...
- 每日一库:cobra 简介
当你需要为你的 Go 项目创建一个强大的命令行工具时,你可能会遇到许多挑战,比如如何定义命令.标志和参数,如何生成详细的帮助文档,如何支持子命令等等.为了解决这些问题,github.com/spf13 ...