博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
不学无数——Mybatis自动映射器Mapper原理分析
阅读量:6388 次
发布时间:2019-06-23

本文共 3000 字,大约阅读时间需要 10 分钟。

在使用MyBatis时,有时候会想,为什么只写一个接口没有编写任何的实现类,但是就能返回接口的实例,并且调用接口的方法返回数据库中的数据?此时脑海中浮现了写动态代理时候的记忆,记得动态代理也是接管了接口,不需要实际的代理角色。然后经过源码的Debug发现果然是运用了动态代理的技术。如果对于动态代理技术不熟悉的同学可以看

Mybatis自动映射器Mapper的源码分析

首先我们想Debug源码就得写一个测试类如下:

@Autowiredprivate SqlSessionFactory sqlSessionFactory;@Testpublic void testMybatis(){    SqlSession sqlSession = sqlSessionFactory.openSession();    TBapCheckPtsTranscdMapper mapper = sqlSession.getMapper(TBapCheckPtsTranscdMapper.class);    TAmsAcPmtDtlPo tAmsAcPmtDtlPo= new TAmsAcPmtDtlPo();    mapper.queryTransCdByType(tAmsAcPmtDtlPo);}复制代码

Mapper是这样的

public interface TBapCheckPtsTranscdMapper {	List
> queryTransCdByType(TAmsAcPmtDtlPo tAmsAcPmtDtlPo); }复制代码

首先先弄明白如何得到的接口的实际对象,由此Debug进去。

TBapCheckPtsTranscdMapper mapper = sqlSession.getMapper(TBapCheckPtsTranscdMapper.class);复制代码

然后进行Debug源码,发现在MapperProxyFactory中,返回了代理对象。

protected T newInstance(MapperProxy
mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); }复制代码

然后发现在执行接口的方法的时候进入到了代理MapperProxy

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {  //诸如hashCode()、toString()、equals()等方法,将target指向当前对象this  if (Object.class.equals(method.getDeclaringClass())) {    return method.invoke(this, args);  } else if (isDefaultMethod(method)) {    return invokeDefaultMethod(proxy, method, args);  }} catch (Throwable t) {  throw ExceptionUtil.unwrapThrowable(t);}final MapperMethod mapperMethod = cachedMapperMethod(method);return mapperMethod.execute(sqlSession, args);}复制代码

自己写一个小例子

首先自己定义个实体类

public class User {    private Integer id;    private String name;    private String age;    -----get,set方法}复制代码

然后Mapper接口如下

public interface UserMapper {    public User findUserById(Integer id);}复制代码

代理类如下

public class MapperProxy implements InvocationHandler {	@SuppressWarnings("unchecked")	public 
T newInstance(Class
clz) { return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz }, this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { try { // 诸如hashCode()、toString()、equals()等方法,将target指向当前对象this return method.invoke(this, args); } catch (Throwable t) { } } //后面的xml解析之类的就先不模拟,在这直接返回数据 return new User((Integer) args[0], "zhangsan", "18"); }}复制代码

测试如下

public static void main(String[] args) {    ClassLoader classLoader = UserMapper.class.getClassLoader();    MapperProxy mapperProxy = new MapperProxy();    //通过代理生成接口的实例对象    UserMapper mapper = (UserMapper) Proxy.newProxyInstance(classLoader, new Class[]{UserMapper.class},mapperProxy);    User user = mapper.findUserById(10000);    System.out.println("ID:" + user.getId());    System.out.println("Name:" + user.getName());    System.out.println("Age:" + user.getAge());}复制代码

打印如下

ID:10000Name:zhangsanAge:18Practice.Day09.MapperProxy@24d46ca6复制代码

转载地址:http://fvdha.baihongyu.com/

你可能感兴趣的文章
iOS Swift编程语言
查看>>
Android 实现闹钟功能
查看>>
graal
查看>>
Win10 安装msi 提示2502、2503的错误代码 -- 命令提示符(管理员) -- msiexec /package...
查看>>
对超线程几个不同角度的解释
查看>>
bitcask存储引擎
查看>>
构建Koa2 + Vue2.0 前后端分离的多页应用
查看>>
音视频--音频入门
查看>>
Reactjs 踏坑指南3:一些例子(未完成)
查看>>
Git很实用的命令
查看>>
Docke的WEB管理工具
查看>>
SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成
查看>>
客户端C++与前端js交互
查看>>
【并发编程】Future模式及JDK中的实现
查看>>
每日 30 秒之 对海量数据进行切割
查看>>
架构的“一小步”,业务的一大步
查看>>
后端_Laravel
查看>>
【跃迁之路】【731天】程序员高效学习方法论探索系列(实验阶段488-2019.2.21)...
查看>>
简化 MongoDB 关联运算
查看>>
62. Unique Paths
查看>>