Mybatis的接口映射原理

1、问题引入

在使用 Mybaits时 ,只需要写一个Mapper 接口(不用写实现类),并在对应的xml 文件中写好 sql 。然后,Mybatis就自动实现了具体的 CRUD 方法调用。

通常我们使用 Mybatis 的主要步骤是:

  • 构建 SqlSessionFactory ( 通过 xml 配置文件 , 或者直接编写Java代码)
  • 从 SqlSessionFactory 中获取sqlSession
  • 从sqlSession 中获取Mapper,例如BlogMapper
  • 调用 Mapper 的方法 ,例如:blogMapper.selectBlog(int blogId)

 由此可知,session.getMapper() 方法内部产生了BlogMapper接口的实现类,因为BlogMapper是接口。

2、接口映射原理

(1)当解析xml配置文件时,会根据<mapper namespace="....">的namespace属性值,判断classpath下有没有这样一个接口的全路径与namespace属性值完全相同,如果有,则建立二者之间的映射关系。

进入XMLMapperBuilder类中,找到bindMapperForNamespace。

(2)进入Configuration类,找到addMapper方法,再进入MapperRegistry类, BlogMapper接口其实是注册在MapperRegistry类中的。

Configuration类实际上将addMapper和getMapper委派给了MapperRegistry来执行:

  • addMapper方法会针对这个Mapper接口生成一个MapperProxyFactory工厂类。
  • getMapper方法,会通MapperProxyFactory工厂类,返回一个Mapper接口的动态代理类。

 由图可知,Mapper接口其实是放到HashMap中,其Key 为当前Class对象,value 为一个MapperProxyFactory 实例。

(3)回过头来看上一节的session.getMapper() 的原理。SqlSession 接口有两个实现类,一个是DefaultSqlSession,另一个是SqlSessionManager。由于在初始化SqlSessionFactory时所调用的SqlSessionFactoryBuilder的build()方法里配置的是DefaultSqlSession,所以进一步进入到DefaultSession类中,看看session.getMapper()是怎么实现的。继续进入getMapper方法中,发现是调用的mapperRegistry的getMapper方法。

综上可知,sqlSession.getMapper(BlogMapper.class)方法先是调用了 configuration的getMapper方法,最终是调用了MapperRegistry的getMapper方法。以BlogMapper的class对象为key,找到了对应的value,也就是mapperProxyFactory对象,然后调用这个对象的newInstance()方法。

(4)进入MapperProxyFactory中,发现是通过Proxy.newProxyInstance方法产生了一个BlogMapper的代理对象,也就是jdk的动态代理。其中三个参数分别为:

  • ClassLoader —— 指定当前接口的加载器
  • 当前被代理的接口 —— 这里就是BlogMapper
  • 代理类是什么 —— 这里就是MapperProxy

 (5)进入代理类MapperProxy中,找到execute方法,该方法中封装了CRUD。

 总结:

当调用sqlSession.getMapper()方法时,就会创建一个新的动态代理对象。

首先,Mybatis会调用XMLMapperBuilder类的bindMapperForNamespace()方法,根据xml文件中的namespace中的属性,去找Mapper接口,如果找到,就通过configuration类(然后是MapperRegistry 类)的addMapper()方法将其注册到MapperRegistry 类的 HashMap中,key是Mapper接口的class对象,value是当前的Mapper的代理工厂对象mapperProxyFactory,然后调用该对象的newInstance()方法去实例化对象,newInstance()里面返回的就是基于jdk的动态代理生成的Mapper接口的代理对象,在代理类MapperProxy 中完成了CRUD的调用。

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值