美文网首页
MapperProxy相关

MapperProxy相关

作者: kacen | 来源:发表于2022-06-23 20:10 被阅读0次

自己创一个demo,然后在:Student student = studentDao.queryById();打断点

...
 public static void main(String[] args) throws IOException {
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      SqlSessionFactory build = builder.build(Resources.getResourceAsReader("mybatis-config.xml"));
      SqlSession sqlSession = build.openSession();

      StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
      Student student = studentDao.queryById();
      System.out.println(student);
      sqlSession.commit();
      sqlSession.close();
  }
...

1.可以看到它调用的是MapperProxy


截屏2022-06-23 上午12.20.10.png
截屏2022-06-23 上午12.22.09.png

2.进入到MapperProxy这里可以看到是invoke 该方法。
方法会先判断该方法是不是一个object类。如果为true直接调用。为false的话从缓存调用器里调用该方法。

截屏2022-06-23 上午12.23.22.png
截屏2022-06-23 上午12.24.56.png
3.我们可以看看它是为false的。
截屏2022-06-23 上午12.29.42.png
MethodProxy中的逻辑代理
MapperProxy.invoke() 方法是代理对象的执行入口,它会拦截所有非object类型的方法。而且针对每个方法都会调用cacheInvoked()方法获取对应的MapperMethod对象。并调用invoke()方法执行对应的代理逻辑及目标方法。
截屏2022-06-24 下午7.52.42.png
从上图可以看到DefaultMethodInvoker和PlainMethodInvoker都是MapperMethodInvoker的实现类。

通过对 MapperProxy 的分析我们知道,MapperMethod 是最终执行 SQL 语句的地方,同时也记录了 Mapper 接口中的对应方法,其核心字段也围绕这两方面的内容展开。
** SqlCommand**
MapperMethod 的第一个核心字段是 command(SqlCommand 类型),其中维护了关联 SQL 语句的相关信息。在 MapperMethod$SqlCommand 这个内部类中,通过 name 字段记录了关联 SQL 语句的唯一标识,通过 type 字段(SqlCommandType 类型)维护了 SQL 语句的操作类型,这里 SQL 语句的操作类型分为 INSERT、UPDATE、DELETE、SELECT 和 FLUSH 五种。

下面我们就来看看 SqlCommand 如何查找 Mapper 接口中一个方法对应的 SQL 语句的信息,该逻辑在 SqlCommand 的构造方法中实现,如下:

截屏2022-06-24 下午7.58.39.png

相对应的解析

//获取接口对应的名称
        final String methodName = method.getName();
        //获取Mapper接口的类型
        final Class<?> declaringClass = method.getDeclaringClass();
        // 将Mapper接口名称和方法名称拼接起来作为SQL语句唯一标识,
        // 到Configuration这个全局配置对象中查找SQL语句
        // MappedStatement对象就是Mapper.xml配置文件中一条SQL语句解析之后得到的对象
        MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
                configuration);
        if (ms == null) {
            // 针对@Flush注解的处理
            if (method.getAnnotation(Flush.class) != null) {
                name = null;
                type = SqlCommandType.FLUSH;
            } else {
                // 没有@Flush注解,会抛出异常
                throw new BindingException("Invalid bound statement (not found): "
                        + mapperInterface.getName() + "." + methodName);
            }
        } else {
            // 记录SQL语句唯一标识
            name = ms.getId();
            // 记录SQL语句的操作类型
            type = ms.getSqlCommandType();
            if (type == SqlCommandType.UNKNOWN) {
                throw new BindingException("Unknown execution method for: " + name);
            }

这里调用的 resolveMappedStatement() 方法不仅会尝试根据 SQL 语句的唯一标识从 Configuration 全局配置对象中查找关联的 MappedStatement 对象,还会尝试顺着 Mapper 接口的继承树进行查找,直至查找成功为止。具体实现如下:


截屏2022-06-24 下午8.03.55.png

相关文章

网友评论

      本文标题:MapperProxy相关

      本文链接:https://www.haomeiwen.com/subject/eyrpvrtx.html