一文带你掌握Mybatis基于Mapper源码解析

297 阅读2分钟

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

Mybatis基于Mapper源码解析

Mapper代码实现

image.png

image.png

由于基于Mapper代理方式前三步和基于XML配置实现方式一样,这次不过多讲解。

强调一点:MyBatis初始化时对接⼝的处理:MapperRegistry是Configuration中的⼀个属性,它内部维护⼀个HashMap⽤于存放mapper接⼝的⼯⼚类,每个接⼝对应⼀个⼯⼚类。mappers中可以配置接⼝的包路径,或者某个具体的接⼝类。

<mappers>
      <mapper class="com.mybatis.mapper.UserMapper"/>
      <package name="com.mybatis.mapper"/>
</mappers>
  • 当解析mappers标签时,它会判断解析到的是mapper配置⽂件时,会再将对应配置⽂件中的增删改查标签封装成MappedStatement对象,存⼊mappedStatements中。

image.png

image.png

image.png 如果mapper里面是package标签,那么会通过configutation类中的addMappers实现类进行扫描该包下的所有Mapper接口,并添加到mapperRegistry中

通过XMLConfigBuilder类中的mapperElement方法进行解析MapperXMl文件的相关信息。 当判断解析到接⼝时,会建此接⼝对应的MapperProxyFactory对象,存⼊HashMap中,key=接⼝的字节码对象,value =此接⼝对应的MapperProxyFactory对象。

getMapper源码解析

首先进入sqlSession.getMapper(UserMapper.class)中

image.png

getMapper的实现类是DefaultSqlSession类,在该类中getMapper方法调用了configuation中的getMapper方法,进入该方法中源码如下图所示:

image.png

configuation中的getMapper方法的实现类是MapperRegistry的getMapper方法,进入该方法源码如下图所示:

image.png

通过传入的参数type值查询map集合获取到MapperProxyFactory,MapperProxyFactory在初始化的过程中,每一个Mapper都会生成对应的MapperProxyFactory并存放的map集合中,如果为空,则直接抛出异常,如果不为空,直接调用mapperProxyFactory.newInstance()方法进行动态代理工厂生成实例。进入该方法源码如下所示:

image.png

使用Proxy.newProxyInstanc()方法调用动态代理,由此可见,sqlSession.getMapper()方法底层就是调用的是JDK的动态代理的实现。然后接收到的就是对应mapper的代理对象

MapperProxy中invoke()方法解析

在动态代理返回了示例后,我们就可以直接调⽤mapper类中的⽅法了,但代理对象调⽤⽅法,执⾏是在MapperProxy中的invoke⽅法中

image.png

image.png

image.png

通过上图代码可以,主要invoke方法主要调用的是mapperMethod.execute()方法。

image.png

基本上execute最终的还是调用的SqlSession中的增删差改方法,而且查询方法还区分了很多方法,具体看源码注释。

由此可知,invoke方法底层还是调用SqlSession方法。