【3-2】Mybatis获取mapper的过程 - 图1

为什么Mybatis只需要接口就可以执行sql?

sqlSession.getMapper()

我们看到下一步是sqlSession.getMapper()获取Mapper的代理对象,这个方法的具体实现如下
image.png

configuration.getMapper()

configuration.getMapper()实现如下
image.png

mapperRegistry.getMapper()

最终追溯到mapperRegistry
image.png

mapperProxyFactory.newInstance()

我们再来看看mapperProxyFactory.newInstance()做了什么
image.png
我们可以看到通过代理工厂获取了mapper的动态代理对象。

插入小知识:https://www.yuque.com/docs/share/d4e1bc97-7899-4108-90a1-d81a69395fba?# 《【3-0】动态代理》

到此为止我们就获得了动态代理对象

动态代理的拦截功能

动态代理对象执行listAllUser()方法,是经过mappeProxy(newProxyInstance的第三个参数)反射调用,执行的具体代码是:
image.png
其首先判断一下执行的方法是不是Object里面的方法(因为所有方法都会走invoke,包括Object中的equals、hashmap方法等),如果是则直接执行,如果不是则执行cachedInvoker方法,该方法具体比较复杂,但是其返回值比较简单
image.png
返回了一个MapperMethodInvoker,其静态代理的MapperMethod对象,具体代码如下:
image.png

mapperMethod.execute()

执行invoke方法即是执行mapperMethod.execute()方法
我们来看一下execute方法是如何执行sql而不需要方法体的吧!
image.png
其中主要的思路是:判断传入的Sql类型,让后调用converArgsToSqlCommandParam方法,然后调用sqlSession的insertupdatedeleteselectList等方法。其实insertdelete底层都是调用的update方法,所以一共就两类方法一种是update、一种是select方法,但是select有很多不同的方法,我们一起来看一下吧。

sqlSession

最终进入SqlSession的以下方法
image.png
image.png
剩下的我们以后再讲吧~

总结

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

userMapper最终生成的是一个代理对象,该代理对象是由sqlSession->configuration->mapperRegister-> mapperProxyFactory利用动态代理生成的

  1. List<UserEntity> userList = userMapper.listAllUser();

userMapper是一个代理对象,其调用任何方法都会经过invoke()方法,执行任何非Object继承过来的方法,会有MapperMethodInvoker.invoke()执行,最终会调用sqlSessionselectupdate相应方法