首页 > 编程语言 >Mybatis 源码(六):Mapper接口代理对象创建

Mybatis 源码(六):Mapper接口代理对象创建

时间:2023-03-20 22:01:15浏览次数:44  
标签:Mapper MapperProxy 对象 代理 接口 sqlSession 源码 Mybatis

  Mapper接口通过sqlSession的getMapper()方法获取,接口无法创建实例对象,获取到的是其代理对象,下面来看看Mapper接口的代理是如何创建的。

 UserMapper mapper = sqlSession.getMapper(UserMapper.class)

  Mapper接口对象创建,DefaultSqlSession#getMapper() 核心代码:

1 // 获取Mapper接口对象
2 public <T> T getMapper(Class<T> type) {
3   // 最终执行 MapperRegistry.getMapper
4   return configuration.<T>getMapper(type, this);
5 }

  Configuration#getMapper() 核心代码:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  return mapperRegistry.getMapper(type, sqlSession);
}

  MapperRegister#getMapper() 核心代码:

 1 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
 2   // 查找指定type对应MapperProxyFactory对象
 3   final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
 4   // 如果mapperProxyFactory为空,则抛出异常
 5   if (mapperProxyFactory == null) {
 6     throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
 7   }
 8   try {
 9     // 创建实现了type接口的代理对象
10     return mapperProxyFactory.newInstance(sqlSession);
11   } catch (Exception e) {
12     throw new BindingException("Error getting mapper instance. Cause: " + e, e);
13   }
14 }

1、获取mapper接口代理工厂对象 - MapperProxyFactory

  通过接口的Class对象,从全局配置对象configuration中mapperRegistry属性对象中获取指定Mapper接口对应的映射代理工厂MapperProxyFactory对象。实际是从mapperRegister的knownMappers属性中获取。

  knownMappers在解析配置过程中完成了初始化,在Mybatis 源码(四):Mapper的解析工作中已做分析,此处不再赘述。

2、创建Mapper接口的代理对象

  mapper接口代理工厂创建接口代理对象,MapperProxyFactory#newInstance() 核心代码:

1 // 创建接口代理对象
2 public T newInstance(SqlSession sqlSession) {
3   // 创建MapperProxy对象,每次调用都会创建新的mapperProxy对象
4   final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
5   return newInstance(mapperProxy);
6 }

1、获取MapperProxy对象

  MapperProxy用于创建Mapper接口的代理对象,类图如下:

 

  MapperProxy继承自InvovationHandler接口,使用JDK动态代理创建代理对象需要使用Proxy的静态方法newProxyInstance,newProxyInstance方法详情:

 

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

 

  在获取Mapper接口的代理对象时,需使用MapperProxy对象作为参数完成代理对象的创建。

  映射器代理 - MapperProxy构造方法详情:
 1 // 会话对象 - sqlSession
 2 private final SqlSession sqlSession;
 3 // mapper接口对应的Class对象
 4 private final Class<T> mapperInterface;
 5 // 用于缓存MapperMethod对象
 6 // key是mapper接口中方法对应的Method对象,value是对应的MapperMethod对象,MapperMethod对象会完成SQL参数转换及SQL语句的执行功能
 7 private final Map<Method, MapperMethod> methodCache;
 8 
 9 // 构造函数
10 public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
11   this.sqlSession = sqlSession;
12   this.mapperInterface = mapperInterface;
13   this.methodCache = methodCache;
14 }

  MapperProxy对象持有sqlSession对象、Mapper接口类型Class对象、方法缓存对象。

2、创建接口代理对象

  重载方法newInstance() 创建接口代理对象,使用JDK动态代理完成Mapper接口代理对象的创建,MapperProxyFactory#newInstance() 核心代码:

 

1 // 使用jdk动态代理完成接口代理对象的创建
2 protected T newInstance(MapperProxy<T> mapperProxy) {
3   // 创建实现了mapperInterface接口的代理对象
4   return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
5 }

3、总结

  根据接口类型 - Class对象,获取全局配置对象configuration中MapperRegister属性对象的knownMappers缓存属性中获取Mapper代理工厂对象创建MapperProxy对象,MapperProxy继承自InvovationHandler接口。

  Mapper接口创建代理对象使用的是JDK动态代理,用MapperProxy作为参数完成代理对象的创建。

 

标签:Mapper,MapperProxy,对象,代理,接口,sqlSession,源码,Mybatis
From: https://www.cnblogs.com/RunningSnails/p/17237992.html

相关文章

  • 尚硅谷MyBatis9_特殊sql的执行
    模糊查询在进行模糊查询的时候,如果使用#{},那么得到的sql语句就会拼接错误。比如:select*fromt_userwhereusernamelike'%#{username}%'执行sql语句转换后会......
  • mybatis 功能 beetl 实现 beetlsql
    beetlsql是使用beetl来完成mybatis功能。同时具有Hibernate优点&Mybatis优点功能,适用于承认以SQL为中心,同时又需求工具能自动能生成大量常用的SQL的应用。S......
  • 尚硅谷MyBatis8_各种查询功能
    查询一个实体类对象查询出的数据只有一条,可以通过「实体类对象」or「集合」or「map」接收/***根据用户id查询用户信息*@paramid*@return*/UsergetUserById(@Pa......
  • Mybatis 源码(五):SqlSession对象构建
    SqlSession对象创建核心在SQL执行器Executor对象的创建,sqlSession持有Executor对象。1、SqlSession对象的创建应用程序每次操作数据库,都需要创建一个sqlSession对象,......
  • Mybatis 源码(四):Mapper的解析工作
    1、Mapper配置方式1、package方式指定包路径:<mappers><packagename="org.snails.mapper"/></mappers>2、resource方式指定mapper.xml文件的相对路径:<map......
  • 视频直播源码,js控制滚动条位置
    视频直播源码,js控制滚动条位置今天遇到一个问题,scrollTop定位滚动条位置时不生效,查找问题发现在给元素设置滚动属性后,直接设置了该元素滚动条的位置,导致该元素没有子元素......
  • resources目录下的mapper写sql语句没有提示
    resources目录下的mapper写sql语句没有提示首先了解一下mybatix-config.xml连接mapper文件的三种方式:<!--第一种--><mapperresource="com/bbl/dao/UserMa......
  • Mybatis缓存
    1.一级缓存同一个SqlSession对象第一次执行查询语句,把结果写入一级缓存之后没有更新插入删除操作,执行相同的查询语句,会读取一级缓存内数据1.1原理SqlSession级别的缓......
  • 【Spring 源码学习系列】BeanNameAware#setBeanName 方法的调用时机
    一、背景前一节我们研究了​​《ApplicationContextAware方法的调用时机》​​,对IOC容器最核心的方法refresh有了初步的了解。这节,我们将借助BeanNameAware方法的......
  • mybatis返回集合对象包含List<String>
    mybatis返回集合对象包含List<String>时间:2021-07-13本文章向大家介绍mybatis返回集合对象包含List<String>,主要包括mybatis返回集合对象包含List<String>使用实例、应用......