不学无数——Mybatis自动映射器Mapper原理分析
发布日期:2021-08-22 06:43:24 浏览次数:3 分类:技术文章

本文共 3077 字,大约阅读时间需要 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

转载地址:https://blog.csdn.net/weixin_33738555/article/details/89628005 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python 数据结构 字典
下一篇:Python3入门机器学习 - Jupyter Notebook篇

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年03月28日 18时12分46秒