广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >直接调用userMapper接口的方法是什么
  • 952
分享到

直接调用userMapper接口的方法是什么

2024-04-02 19:04:59 952人浏览 薄情痞子
摘要

本篇内容主要讲解“直接调用userMapper接口的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“直接调用userMapper接口的方法是什么”吧!老

本篇内容主要讲解“直接调用userMapper接口的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“直接调用userMapper接口的方法是什么”吧!

老规矩,先上案例代码,这样大家可以更加熟悉是如何使用的,看过mybatis系列的小伙伴,对这段代码差不多都可以背下来了。

哈哈~,有点夸张吗?不夸张的,就这行代码。

public class MybatisApplication {         public static final String URL = "jdbc:Mysql://localhost:3306/mblog";         public static final String USER = "root";         public static final String PASSWord = "123456";              public static void main(String[] args) {             String resource = "mybatis-config.xml";             InputStream inputStream = null;             sqlSession sqlSession = null;             try {                 inputStream = Resources.getResourceAsStream(resource);                 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);                 sqlSession = sqlSessionFactory.openSession();                 //今天主要这行代码                 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);                 System.out.println(userMapper.selectById(1));                  } catch (Exception e) {                 e.printStackTrace();             } finally {                 try {                     inputStream.close();                 } catch (IOException e) {                     e.printStackTrace();                 }                 sqlSession.close();             }         }

看源码有什么用?

通过源码的学习,我们可以收获Mybatis的核心思想和框架设计,另外还可以收获设计模式的应用。

前两篇文章我们已经Mybatis配置文件解析到获取SqlSession,下面我们来分析从SqlSession到userMapper:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

前面那篇文章已经知道了这里的sqlSession使用的是默认实现类DefaultSqlSession。所以我们直接进入DefaultSqlSession的getMapper方法。

//DefaultSqlSession中   private final Configuration configuration; //type=UserMapper.class @Override public <T> T getMapper(Class<T> type) {   return configuration.getMapper(type, this); }

这里有三个问题:

直接调用userMapper接口的方法是什么

问题1:getMapper返回的是个什么对象?

上面可以看出,getMapper方法调用的是Configuration中的getMapper方法。然后我们进入Configuration中

//Configuration中   protected final MapperReGIStry mapperRegistry = new MapperRegistry(this); ////type=UserMapper.class public <T> T getMapper(Class<T> type, SqlSession sqlSession) {     return mapperRegistry.getMapper(type, sqlSession); }

这里也没做什么,继续调用MapperRegistry中的getMapper:

//MapperRegistry中 public class MapperRegistry {   //主要是存放配置信息   private final Configuration config;   //MapperProxyFactory 的映射   private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();    //获得 Mapper Proxy 对象   //type=UserMapper.class,session为当前会话   public <T> T getMapper(Class<T> type, SqlSession sqlSession) {     //这里是get,那就有add或者put     final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);     if (mapperProxyFactory == null) {       throw new BindingException("Type " + type + " is not known to the MapperRegistry.");     }    try {       //创建实例       return mapperProxyFactory.newInstance(sqlSession);     } catch (Exception e) {       throw new BindingException("Error getting mapper instance. Cause: " + e, e);     }   }      //解析配置文件的时候就会调用这个方法,   //type=UserMapper.class   public <T> void addMapper(Class<T> type) {     // 判断 type 必须是接口,也就是说 Mapper 接口。     if (type.isInterface()) {         //已经添加过,则抛出 BindingException 异常         if (hasMapper(type)) {             throw new BindingException("Type " + type + " is already known to the MapperRegistry.");         }         boolean loadCompleted = false;         try {             //添加到 knownMappers 中             knownMappers.put(type, new MapperProxyFactory<>(type));             //创建 MapperAnnotationBuilder 对象,解析 Mapper 的注解配置             MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);             parser.parse();             //标记加载完成             loadCompleted = true;         } finally {             //若加载未完成,从 knownMappers 中移除             if (!loadCompleted) {                 knownMappers.remove(type);             }         }     } } }

MapperProxyFactory对象里保存了mapper接口的class对象,就是一个普通的类,没有什么逻辑。

在MapperProxyFactory类中使用了两种设计模式:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 单例模式methodCache(注册式单例模式)。

  3. 工厂模式getMapper()。

继续看MapperProxyFactory中的newInstance方法。

public class MapperProxyFactory<T> {       private final Class<T> mapperInterface;       private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();            public MapperProxyFactory(Class<T> mapperInterface) {         this.mapperInterface = mapperInterface;       }      public T newInstance(SqlSession sqlSession) {       //创建MapperProxy对象       final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);       return newInstance(mapperProxy);     }     //最终以jdk动态代理创建对象并返回      protected T newInstance(MapperProxy<T> mapperProxy) {         return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);     }     }

从代码中可以看出,依然是稳稳的基于 JDK Proxy 实现的,而 InvocationHandler 参数是 MapperProxy 对象。

//UserMapper 的类加载器 //接口是UserMapper //h是mapperProxy对象 public static Object newProxyInstance(ClassLoader loader,                                           Class<?>[] interfaces,                                        InvocationHandler h){ }

问题2:为什么就可以调用他的方法?

上面调用newInstance方法时候创建了MapperProxy对象,并且是当做newProxyInstance的第三个参数,所以MapperProxy类肯定实现了InvocationHandler。

进入MapperProxy类中:

//果然实现了InvocationHandler接口   public class MapperProxy<T> implements InvocationHandler, Serializable {        private static final long serialVersionUID = -6424540398559729838L;     private final SqlSession sqlSession;     private final Class<T> mapperInterface;     private final Map<Method, MapperMethod> methodCache;        public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {       this.sqlSession = sqlSession;       this.mapperInterface = mapperInterface;       this.methodCache = methodCache;     }     //调用userMapper.selectById()实质上是调用这个invoke方法     @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {       try {         //如果是Object的方法toString()、hashCode()等方法           if (Object.class.equals(method.getDeclarinGClass())) {           return method.invoke(this, args);         } else if (method.isDefault()) {           //JDK8以后的接口默认实现方法             return invokeDefaultMethod(proxy, method, args);         }       } catch (Throwable t) {         throw ExceptionUtil.unwrapThrowable(t);       }       //创建MapperMethod对象       final MapperMethod mapperMethod = cachedMapperMethod(method);       //下一篇再聊       return mapperMethod.execute(sqlSession, args);     }   }

也就是说,getMapper方法返回的是一个JDK动态代理对象(类型是$Proxy+数字)。这个代理对象会继承Proxy类,实现被代理的接口UserMpper,里面持有了一个MapperProxy类型的触发管理类。

当我们调用UserMpper的方法时候,实质上调用的是MapperProxy的invoke方法。

userMapper=$Proxy6@2355。

直接调用userMapper接口的方法是什么

为什么要在MapperRegistry中保存一个工厂类?

原来他是用来创建并返回代理类的。这里是代理模式的一个非常经典的应用。

直接调用userMapper接口的方法是什么

MapperProxy如何实现对接口的代理?

JDK动态代理

我们知道,JDK动态代理有三个核心角色:

  • 被代理类(即就是实现类)

  • 接口

  • 实现了InvocationHanndler的触发管理类,用来生成代理对象。

被代理类必须实现接口,因为要通过接口获取方法,而且代理类也要实现这个接口。

直接调用userMapper接口的方法是什么

而Mybatis中并没有Mapper接口的实现类,怎么被代理呢?它忽略了实现类,直接对Mapper接口进行代理。

MyBatis动态代理:

在Mybatis中,JDK动态代理为什么不需要实现类呢?

直接调用userMapper接口的方法是什么

这里我们的目的其实就是根据一个可以执行的方法,直接找到Mapper.xml中statement ID ,方便调用。

最后返回的userMapper就是MapperProxyFactory的创建的代理对象,然后这个对象中包含了MapperProxy对象,

问题3:到底是怎么根据Mapper.java找到Mapper.xml的?

最后我们调用userMapper.selectUserById(),本质上调用的是MapperProxy的invoke()方法。

请看下面这张图:

直接调用userMapper接口的方法是什么

如果根据(接口+方法名找到Statement ID  ),这个逻辑在InvocationHandler子类(MapperProxy类)中就可以完成了,其实也就没有必要在用实现类了。

到此,相信大家对“直接调用userMapper接口的方法是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 直接调用userMapper接口的方法是什么

本文链接: https://www.lsjlt.com/news/84116.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 直接调用userMapper接口的方法是什么
    本篇内容主要讲解“直接调用userMapper接口的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“直接调用userMapper接口的方法是什么”吧!老...
    99+
    2022-10-19
  • java调用restful接口的方法是什么
    Java调用RESTful接口的方法有多种,以下是其中几种常用的方法:1. 使用Java内置的URLConnection类:可以通过...
    99+
    2023-10-08
    java
  • springboot调用restful接口的方法是什么
    在Spring Boot中调用RESTful接口有多种方法。以下是其中的一些常用方法:1. 使用RestTemplate:RestT...
    99+
    2023-09-15
    springboot
  • java接口异步调用的方法是什么
    在Java中,可以使用以下几种方法来实现接口的异步调用: 使用回调函数(Callback):在接口中定义一个回调方法,然后在调用方...
    99+
    2023-10-25
    java
  • java调用c语言接口的方法是什么
    Java调用C语言接口的方法主要有以下几种:1. 使用Java Native Interface(JNI):JNI是Java提供的一...
    99+
    2023-08-08
    java c语言
  • java调用dubbo接口测试的方法是什么
    在Java中调用Dubbo接口进行测试有以下几种方法:1. 使用Dubbo提供的测试框架:Dubbo提供了一个Mock框架,可以用于...
    99+
    2023-10-20
    java dubbo
  • java跨项目调用接口的方法是什么
    在Java中,实现跨项目调用接口的方法有几种:1. 使用Java远程方法调用(Java Remote Method Invocati...
    99+
    2023-09-22
    java
  • spring多线程调用接口的方法是什么
    在Spring中,可以使用多线程来调用接口的方法。有多种方法可以实现多线程调用接口的方式,以下是其中一种常见的方式:1. 使用`@A...
    99+
    2023-08-14
    spring
  • golang接口异步回调的方法是什么
    在Go语言中,可以使用Goroutine和通道来实现异步回调。首先,定义一个接口类型,并在接口中声明回调方法。例如:gotype C...
    99+
    2023-10-20
    golang
  • php直接调用js的方法名
    PHP作为一种非常流行的后端语言,被广泛用于构建各种类型的网站和应用程序。与此同时,JavaScript作为一种前端语言,被广泛用于交互式 Web 界面的开发。在许多情况下,开发人员需要通过PHP直接调用 JavaScript函数。在本篇文...
    99+
    2023-05-14
    php
  • python调用接口上传文件的方法是什么
    在 Python 中调用接口上传文件的方法可以使用 `requests` 库实现。下面是一个示例代码,演示了如何使用 `reques...
    99+
    2023-10-08
    python
  • python调用接口获取数据的方法是什么
    在Python中调用接口获取数据的方法有几种:1. 使用内置的`urllib`或`urllib2`模块进行接口调用。这些模块提供了H...
    99+
    2023-08-29
    python
  • php怎么直接调用js的方法名
    本篇内容主要讲解“php怎么直接调用js的方法名”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php怎么直接调用js的方法名”吧!使用PHP调用JavaScript函数PHP可以通过使用Java...
    99+
    2023-07-05
  • java多线程并发调用接口的方法是什么
    在Java中,可以使用多线程并发调用接口的方法有以下几种方式:1. 实现Runnable接口:创建一个类,实现Runnable接口,...
    99+
    2023-08-14
    java
  • Java微服务间接口调用feign的方法是什么
    今天小编给大家分享一下Java微服务间接口调用feign的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Feign...
    99+
    2023-07-05
  • SpringCloud服务接口调用OpenFeign及使用的方法是什么
    这篇“SpringCloud服务接口调用OpenFeign及使用的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“S...
    99+
    2023-07-05
  • mongodb做接口的方法是什么
    使用MongoDB作为接口的方法主要有以下几种:1. 使用MongoDB自带的驱动程序:MongoDB提供了多种编程语言的驱动程序,...
    99+
    2023-08-30
    mongoDB
  • 搭建云服务器及调用接口的方法是什么
    搭建云服务器的方法:1.选择云服务器提供商。2.注册账号并完成实名认证。3.选择合适的云服务器规格和操作系统,如Linux或Wind...
    99+
    2023-06-11
    搭建云服务器 云服务器
  • java调用接口的原理是什么
    Java调用接口的原理是通过接口的实现类来实现接口的方法。当一个类实现了一个接口,它必须实现接口中声明的所有方法。然后可以通过创建实...
    99+
    2023-10-09
    java
  • java直接打印对象的方法是什么
    在Java中,可以使用`System.out.println()`方法来直接打印对象。这个方法会自动调用对象的`toString()...
    99+
    2023-10-11
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作