mybatis源码分析:Mapper接口是什么
在《mybatis源码分析:启动过程》中分析了mybatis的启动过程,mybatis的启动过程主要集中在解析其核心配置文件(mybatis-config.xml)上,把配置文件中的配置全部解析到Configuration类中,每个配置在Configuration中均能找到其设置。本文分析mybatis中的查询接口(例,UserMapper)。
一、概述
在编写mybatis的程序时,常见的做法时编写一个Mapper接口,再编写相应的映射文件,之后便可以初始化mybatis的环境,调用该接口的方法执行操作数据库的各中操作。那么Mapper接口是什么对象那,是怎样和映射文件关联,最后又怎样执行方法的。今天先分析Mapper接口,具体的环境可参考《mybatis源码分析:启动过程》中的相关代码。这里先给出一个结论,Mapper接口是使用JDK代理生成的一个代理类。
二、详述
上面说到Mapper接口是使用JDK动态代理生成的一个代理类,下面通过代码去分析,下面是我测试的代码片段,
package cn.com.mybatis.test; import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import cn.com.mybatis.dao.UserMapper; public class TestMybatis { public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(Resources.class.getClassLoader());
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
SqlSession session=factory.openSession();
UserMapper userMapper=session.getMapper(UserMapper.class);
// session.insert("");
System.out.println("userMapper:"+userMapper); userMapper.getUser(); } }
上面从SqlSession中调用getMapper方法,传入一个XXMapper.class的参数,这里传入UserMapper.class(必须是接口 ?),返回的是一个UserMapper的对象,那么这个返回的值到底是什么那,我们分析源码。我们值得这里的session是一个DefaultSqlSession对象,看其方法,
@Override
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
调用了Configuration对象的getMapper方法,
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
调用了mapperRegistry的getMapper方法,
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//根据Class对象获得一个MapperProxyFactory
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//生成一个目标对象的JDK代理对象,并返回
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
从上面可以看到从knownsMappers中根据type返回一个MapperProxyFactory,直译过来就是Mapper接口的代理工厂,mybatis的无处不在的工厂模式啊。
下面看knownsMappers的定义,

从上面可以看出knownMappers中使用map存储,其值为MapperProxyFactory,看下MapperProxyFactory的定义,

从上面可以看到该类有一个构造方法,该构造方法的参数也是一个Class对象,参数名称为mapperInterface,从方法名直译过来就是我们写的Mapper接口。
上面了解了knownsMappers和MapperProxyFactory后,可以知道knownsMappers中的value是根据Mapper接口生成的,那么取出来的值必为当前key的一个MapperProxyFactory,即该对象中的mapperInterface为key值。
根据Class取出其对应的MapperProxyFactory后,下面调用其newInstance方法,如下

下面看其newInstance方法,
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
生成一个MapperProxy对象,
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
上面仅是给三个字段赋值,再看后面的方法,MapperProxyFactory的newInstance(mapperProxy)方法,
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//JDK动态代理
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
从上面可以看到是标准的JDK动态代理生成对象的放式,不再赘述。从这里看出返回的是一个Mapper接口的动态代理对象,第三个参数mapperProxy必然实现了InvocationHandler接口,看其定义

可以看到实现了InvocationHandler接口,那么在调用Mapper接口的时候肯定会执行MapperProxy的invoke方法,这里执行过程下次再分析。
三、总结
本文分析了mybatis中Mapper接口的类型,即从mybatis中取出时是什么类型,这里是一个JDK的动态代理,所以我们要写的是一个接口,因为JDK动态代理是基于接口生成一个代理实现类。

原创不易,有不正之处欢迎指正。
mybatis源码分析:Mapper接口是什么的更多相关文章
- MyBatis 源码分析——SqlSession接口和Executor类
mybatis框架在操作数据的时候,离不开SqlSession接口实例类的作用.可以说SqlSession接口实例是开发过程中打交道最多的一个类.即是DefaultSqlSession类.如果笔者记得 ...
- MyBatis源码分析(3)—— Cache接口以及实现
@(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...
- 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(5)——内置DataSource实现
@(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- Mybatis源码分析-BaseExecutor
根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...
- mybatis源码分析(一)
mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...
随机推荐
- Git三大区域
1.工作区 2.暂存区 3.版本库
- 最好的在线PDF转换工具服务
工作中有时候会碰到需要转换PDF文件的情况,现在网上就要很多免费的在线工具,可以进行PDF文件的转换,下面就来介绍一些可以直接在浏览器中将文档.电子表格.和图片转换为PDF或者互相转换的服务工具. ...
- margin的用法 清除默认样式 display属性值 块状元素 内联元素 行内块元素
margin的用法: 1,margin是在元素的宽高以外的 2,作用:控制元素之间的位置关系 3,margin不能改变盒子本身大小的 4,单一一个方向设置margin值: margin-left ...
- LeetCode 683. K Empty Slots K 个空花盆 / LintCode 861. K个空的位置 (C++/Java)
题目: 一个花园有N个位置.每个位置上有一朵花.这N朵花会在N天内逐一盛开.每天都一定会有并且只有一朵花盛开,从这天起,这朵花将一直处于盛开的状态. 给定一个由数字1到N组成的数组flowers.数组 ...
- AT_agc044_c
problem & blog 由于看到和三进制有关的操作,可以想到建造每个结点都有三个儿子的 Trie.考虑维护两种操作. 1.Salasa 舞 对于这种操作,就是把每一个节点的第一个儿子和第 ...
- vue2 混入 (mixin) 带来的小惊喜
最近在review自己写的代码时发现,在很多的地方都用了以下的代码块 1 async initCode() { 2 const resSource = await this.$API.syscode. ...
- C++面向对象多级菜单向Arduino的移植
前段时间写了一篇文章<C++面向对象语言自制多级菜单>,文中指出了可以将HeleMenu库进行移植,现已完成技术思路,特此记录. 一.特性 基本与上一篇文章指出的一致,只是将菜单显示和响应 ...
- Stable Diffusion(二)WebUI使用指南
1. 前言 基于 https://stable-diffusion-art.com/ 内的教程进行翻译与整理,帮助快速上手 stable-diffusion 的使用. 2. 环境 AWS DeepLe ...
- BI小班课程表:PowerBI、finebi、quickbi,每周开课
为了帮助更多BI的友友更好的接触BI,并应用于实践工作中,我决定将我这些年的工作经验和付费咨询的实际经验,拿出一部分基础并且实用的知识和方法整理成课程.其中 PowerBI十节课,计划20个小时: F ...
- 从Java开发者到.NET Core初级工程师学习路线:C#语言基础
1. C#语言基础 1.1 C#语法概览 欢迎来到C#的世界!对于刚从Java转过来的开发者来说,你会发现C#和Java有很多相似之处,但C#也有其独特的魅力和强大之处.让我们一起来探索C#的基本语法 ...