MyBatis核心流程三大阶段之代理阶段(binding模块分析)

啃下MyBatis源码系列目录

啃下MyBatis源码 - 为什么要看MyBatis源码及源码结构

啃下MyBatis源码 - org.apache.ibatis.logging包源码分析

啃下MyBatis源码 - org.apache.ibatis.datasource包源码分析

啃下MyBatis源码 - org.apache.ibatis.cache包源码分析

啃下MyBatis源码 - MyBatis核心流程三大阶段之初始化阶段

啃下MyBatis源码 - MyBatis核心流程三大阶段之代理阶段(binding模块分析)

啃下MyBatis源码 - MyBatis核心流程三大阶段之数据读写阶段

啃下MyBatis源码 - MyBatis面试题总结

--------------------------------------------------------------------------------------------------------------------------

啃下MyBatis源码 - MyBatis核心流程三大阶段之代理阶段(binding模块分析)

1.MyBatis是如何做到面向Mapper接口编程?

2.代理阶段流程梳理

--------------------------------------------------------------------------------------------------------------------------

1.MyBatis是如何做到面向Mapper接口编程?

       只有接口,没有实现类,那么我们很容易会想到是通过解析xml配置文件+动态代理来实现的。我们先来说下MyBatis动态代理实际做了一些什么事情,我们正常编写的代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User uer = userMapper.selectByPrimarKey(1);

       MyBatis动态代理后执行的为下面这段代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
User uer = sqlSession.selectOne("com.en.iot.mapper."+"UserMapper.selectByPrimarKey",1);

       我们可以看到MyBatis动态代理主要做的是翻译的工作,主要翻译的内容有三点:

       1、找到Session中对应的方法执行

       2、找到命名空间和方法名

       3、传递参数

       这三项工作主要是由MapperMethod这个类来实现的,解读这个类之前,我们有必要对binding模块进行一个整体的分析:

MapperRegistry:为MyBatis配置类Configuration类中一个重要的属性,它是mapper接口和对应的代理对象工厂的注册中心;

public class MapperRegistry {
   private final Configuration config;
   //mapper接口和对应的代理对象工厂之间的关系
   private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
   ...
}

MapperProxyFactory:用于生成mapper接口动态代理的实例对象;

public class MapperProxyFactory<T> {
  ...
  //key为mapper接口中的某个方法的method对象,value为对应的MapperMethod
  private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
  ...
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
}

MapperProxy:实现InvocationHandler接口,它是增强mapper接口的实现;

        接着跟进cachedInvoker(method).invoke(proxy, method, args, sqlSession)方法

       我们可以看到在cachedInvoker中判断了一下是选用DefaultMethodInvoker还是PlainMethodInvoker

       我们可以看到在PlainMethodInvoker类中封装了一个MapperMethod对象,然后在invoke方法中的execute方法中最终通过增删改查的类型来调用增强的方法,当然调用前先用参数解析器过滤一下参数。

       那么我们大胆猜测一下,调用execute的这个MapperMethod类中一定保持着Mapper接口中对应方法以及对应的sql语句的信息。


       通过观察这三个对象的构造方法我们可以看到,这三个对象全部是从Configuration类中获取信息,由此证实了我们的猜想,MapperMethod类中通过这三个对象建立mapper接口和配置文件sql语句的联系。

2.代理阶段流程梳理

       1、先从Configuration配置类MapperRegistry对象中获取mapper接口和对应的代理对象工厂信息(MapperProxyFactory)

       2、利用代理对象工厂MapperProxyFactory创建实际代理类(MapperProxy)

       3、在MapperProxy类中通过MapperMethod类对象内保存的中对应方法的信息,以及对应的sql语句的信息进行分析,最终确定对应的增强方法进行调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值