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的调用。
————————————————
原文链接:https://blog.csdn.net/qq_42098875/article/details/118967624
标签:Mapper,getMapper,调用,映射,接口,BlogMapper,Mybatis,方法 From: https://www.cnblogs.com/forestwolf/p/18096876