mybatis源码探究(-)MapperProxyFactory&MapperProxy
在MyBatis中MapperProxyFactory,MapperProxy,MapperMethod是三个很重要的类。
弄懂了这3个类你就大概清楚Mapper接口与SQL的映射,
为什么是接口,没有实例类也可以完成注入或者调用。
其中MapperMethod可以参考:MapperMethod源码分析传送门
在调用MyBatis的addMapper的时候如果你跟踪源码就会最终跟到MapperRegistry的addMapper中有如下的语句:
knownMappers.put(type, new MapperProxyFactory<T>(type));
type就是Mapper接口。下面我们来看一下MapperProxyFactory的源码。
MapperProxyFactory
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethod> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
MapperProxyFactory一看名字我们就知道肯定是一个工厂类,就是为了生成MapperProxy。其实MapperProxyFactory也非常简单。首先看2个成员mapperInterface就是Mapper接口,methodCache就是对Mapper接口中的方法和方法的封装类(MapperMethod)的映射。MapperMethod处理的事情主要就是:处理Mapper接口中方法的注解,参数,和返回值。如果想了解更多的细节可以参考MapperMethod源码分析传送门
然后就是2个newInstance,看名字就知道是工厂方法,一个是protected,一个是public,所以首先看public方法。发现有一个参数SqlSession,SqlSession处理的其实就是执行一次SQL的过程。其实public的newInstance就是new了一个MapperProxy,关于MapperProxy可以先看一下后面的MapperProxy。然后调用了protected的newInstance。
接着我们看protected的newInstance。protected简单明了,就是使用Java Proxy的工厂方法生成一个了Mapper接口的代理类。我想都关系MyBatis源码了应该对Java的Proxy动态代理方式应该非常熟悉了。如果不熟悉可以参考一下我之前写的一篇关于Java动态代理的Java动态代理细探
我们指定MapperProxy实现了InvocationHandler,所以调用Mapper接口中的方法走的是MapperProxy的invoke。而MapperProxy的invoke是把Method包装成了MapperMethod,MapperMethod处理了Mapper接口方法与xml映射的关系。是不是串联起来了。
MapperProxy
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
}
我们看MapperProxy实现了InvocationHandler接口,不用仔细想,基本上是因为Java动态代理。
既然实现了InvocationHandler接口那么当然要先看一下invoke方法了。首先检查了如果是Object中方法就直接调用方法本身。
如果不是就把方法Method包装成MapperMethod,我们前面已经提到了MapperMethod主要就是处理方法的注解,参数,返回值,参数与SQL语句中的参数的对应关系。再次打一波广告,如果像了解更多MapperMethod的细节可以参考MapperMethod源码分析传送门
因为把Method处理为MapperMethod还是一个比较重的操作,所以这里做了缓存处理。
小结
总结一下,我们公共MyBatis添加的Mapper的操作实际上添加的是MapperProxyFactory,这个是MapperProxy的工厂类,但是MapperProxyFactory生产的也不是MapperProxy,而是Mapper的Proxy代理。使用的InvocationHandler是MapperProxy,MapperProxy的invoke方法实际上是把Mapper接口方法包装为了MapperMethod,并执行的MapperMethod的execute方法。MapperMethod处理的逻辑是Mapper方法与xml中的SQL的一些映射关系。例如@MapKey等注解的处理,一些如RowBounds特殊参数的处理以及一些其他关于Mapper方法与SQL映射的处理。执行SQL的逻辑其实是委托给了SqlSession相关的逻辑。
mybatis源码探究(-)MapperProxyFactory&MapperProxy的更多相关文章
- Mybatis日志源码探究
一.项目搭建 1.pom.xml <dependencies> <dependency> <groupId>log4j</groupId> <ar ...
- Spring Framework自动装配setAutowireMode和Mybatis案例的源码探究
由前文可得知, Spring Framework的自动装配有两种方式:xml配置和注解配置: 自动装配的类型有: (1)xml配置中的byType根据类型查找(@Autowired注解是默认根据类型查 ...
- Mybatis源码解析 - mapper代理对象的生成,你有想过吗
前言 开心一刻 本人幼教老师,冬天戴帽子进教室,被小朋友看到,这时候,有个小家伙对我说:老师你的帽子太丑,赶紧摘了吧.我逗他:那你好好学习,以后给老师买个漂亮的?这孩子想都没想立刻回答:等我赚钱了,带 ...
- MyBatis源码解读(3)——MapperMethod
在前面两篇的MyBatis源码解读中,我们一路跟踪到了MapperProxy,知道了尽管是使用了动态代理技术使得我们能直接使用接口方法.为巩固加深动态代理,我们不妨再来回忆一遍何为动态代理. 我相信在 ...
- Mybatis源码解析-MapperRegistry注册mapper接口
知识储备 SqlsessionFactory-mybatis持久层操作数据的根本,具体的解析是通过SqlSessionFactoryBean生成的,具体的形成可见>>>Spring ...
- Mybatis源码解析-MapperRegistry代理注册mapper接口
知识储备 SqlsessionFactory-mybatis持久层操作数据的前提,具体的解析是通过SqlSessionFactoryBean生成的,可见>>>Spring mybat ...
- 【转】Mybatis源码解读-设计模式总结
原文:http://www.crazyant.net/2022.html?jqbmtw=b90da1&gsjulo=kpzaa1 虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开 ...
- MyBatis 源码分析 - SQL 的执行过程
* 本文速览 本篇文章较为详细的介绍了 MyBatis 执行 SQL 的过程.该过程本身比较复杂,牵涉到的技术点比较多.包括但不限于 Mapper 接口代理类的生成.接口方法的解析.SQL 语句的解析 ...
- Mybatis源码解读-设计模式总结
虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...
随机推荐
- 团队冲刺DAY7
团队冲刺DAY7 今天是2019.6.2,交项目的最后一天. 今天的任务是将之前写好的服务器和加解密算法以及图形界面有机结合在一起. 早上8:00,坐在电脑前,一脸懵,因为图形界面不是很懂,所以不知道 ...
- 爬虫 fake_useragent
import requests from fake_useragent import UserAgent ua = UserAgent() headers = { "UserAgent&qu ...
- (59)C# IIS Express 设置
支持非localhost访问 本地测试时 修改 localhost改成127.0.0.1
- java对象属性为date oracle数据库字段为Timestamp 处理方式
解决方案 SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); java.util.Date da ...
- SQL之in和like的连用实现范围内的模糊查询
我们知道in可以实现一个范围内的查询,like可以实现模糊查询, 如 select *where col like 123%但是我们如果有一列attri,如123,132,165... 我们想实现12 ...
- PicoCTF 2013 Dark Star 分析
0x00题目 题目可以从GitHub中找到:https://github.com/picoCTF/2013-Problems/blob/master/Dark%20Star/darkstar.img ...
- Ettercap详细参数
关于界面:ettercap提供 4 种运行界面: Text #文本模式,参数 -T ,一般配合 -q(安静模式)使用 Curses/GTK #图形模式,参数 -C ...
- 微信小程序 Page构造函数重写
//utils/utils.js const oldPage = Page; console.log(oldPage) Page = function (app) { //定义新函数 app.newS ...
- upc组队赛5 Ingenious Lottery Tickets【排序】
Ingenious Lottery Tickets 题目描述 Your friend Superstitious Stanley is always getting himself into trou ...
- composer 配置镜像
阿里云镜像:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ 腾讯云镜像:composer ...