来了,终于来了,大活来了,虽然只有20分钟,但我觉得我要花一个小时。我终于要把源码翻过去了,只要看完这节讠
这是那个核心代码吗?
点开这个new MapperProxy
他直接显示的声明了,不是匿名内部类
他重写了invoke!! 还可以重写这个??
。。这就是学完了代码,不敲的后果,Invoke就是用来重写的
return Object.class.equals(method.getDeclaringClass()) ?
method.invoke(this, args)
: this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession)
上面那个是代码更新了的版本,老师这个是旧版的
走了上面这行,看我标记的黑色箭头,就是实例化了代理对象
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
mapperProxy应该是invocation那个才对,我看看
没错,就是个invacation什么的
所以最终返回的这个mapper 其实是个代理对象
准确的说是SysroleMapper 的代理对象
不一样的地方是,他没有被代理对象,还可以这么用的吗,真灵活!!!
调用这个代理方法,看看它进入到哪里去
说是应该进入这个方法
就是这个invoke
因为这个代理对象,持有了这个incovationHandle 对象
有点懂了,这个incovationHandle 里面其实可以不执行被代理的对象方法的,因为之前是判断是不是之前的我不需要的方法。
就是mybatis的动态代理类,其实想走的是这个方法
重写的这个方法,是干什么的啊?
好复杂啊,那个proxy的形参,就是外面传进来的session这个实参
这个session里的东西好多啊
我忘了,这个对象,是啥了
是被代理对象,这里它没有被代理,给他当成代理了
类加载器
Classloader 类加载器,用来加载Java类到 Java 虚拟机中的一种加载器。
我不行了,快往下捋把,细节问题再说
method.getDeclaringClass()得到方法所在的类
这个判断的意思是,如果你执行的代码是object里面的方法
toString() hasjCode equels
比如调的是这个方法,就会进上面的方法
往下的执行步骤
1、去缓存里面找方法
看看这个里面在做什么
这行代码得到一个 MapperMethod 就是映射方法对象把
method是个对象
F7进去
看看MapperMethod这个方法在干什么
我的方法和老师的方法,已经不一样了
我的是这样的
我看了一眼,方法确实不一样了,先安老师的来吧
好了,继续捋
看看MapperMethod这个方法在干什么
把我们的method封装到了一个叫做MapperMethod的方法里了
接着看里面在干什么
确实是个内部类,看看再干什么
好像是原始的那种 不用getMapper的方法
判断configurration 里面有没有这个 方法
这个东西之前存进去了
继续那个判断
包含这个,之前build的时候已经存进去了
得到一个mapperState对象
终于走完了这个方法,存进去了
就是缓存了一下这个方法
所以映射文件这里需要是接口名和方法名
在运行的时候,他根据配置文件里面的接口名和方法 名 拼了个字符串
解析的时候就能找到这个方法了,是这么设计好的
去执行这个方法
2、进execute方法
看看execute方法,mybatis用动态代理,就是为了执行这个方法吧
这里判断这个方法是不是无返回值的 return void void 无效的
有返回值的
再去判断是不是returnMany
怎么判断的
直接去configuration里面取值了,说明之前已经判断过了
判断是不是集合 是不是数组
他是怎么判断是不是集合的
isAssignavleFrom 用来判断,这个类type 是不是Collection(集合)的子类
判断是不是数组
jdk里面原生的东西,暂时看不了,本地方法
就算他是many在的是这个方法
他就去调用自己的selectList方法,妈的整了半天就是封装了自己之前的selectOne 什么寄吧东西
是不是map也是这么弄得
走sqlSession的selectMap方法
是不是游标查询
老师说这个方法早就淘汰了
最后走到了这里面
convertArgsToSqlCommandParam == 转换参数到sql命令指令需要的参数格式== 你看这名字起的多好 啊
转换这个
配置文件之前有的paramType 这个,这个里面没有,意思一下,反正我懂
因为这里是一个简单的string所以不用转
这个转换方法相当NB
简单说明一下这个方法的实现
1、如果你的参数没有注解,并且参数只有一个
就简单的放到这里面了 Object 数组
this.name.firstKey 是什么,老师没讲,我大概看了一眼,好像是map里面的一个key
SortedMap 是一个map
2、如果你的参数有注解,并且参数不止有一个
否则new 了一个paramMap
这个paramMap 好像是他自己定义的的一个hashMap子类
所以他底层,帮我们把参数封装成了map
param0 param1 还记的这个吗,如果没用注解指定,可以直接用这个来着
我的那个方法 参数是 String 所以不需要转换
getname的值
就是命名空间加方法名
至于selectOne 怎么执行的,这个就有点深了
老师进的是红框下面的方法,里面至少有八九层,我的妈啊吗,唉,我真是个彩笔
总结一下,核心就是
理解getMapper
就是封装了selectone list 什么的方法
拿到了getMapper,返回了一个代理对象
拿到了代理对象执行了对应方法的过程
我还有一个问题,为什么他要是用动态代理模式来做呢?
我想想,如果不用动态代理,那他该怎么做呢?
好像是为了实现这个
使用动态代理,就是为了分流这个方法吧,如果我直接用invoke的话,会是什么情况呢?
如果直接invoke就不能区分 selectone 还有 selectList 这些方法了吧
应该吧
如果直接invoke的话
啊,使用动态代理是为了使用那个大反射,大反射是为了干什么来着
动态代理就是静态代理的加强版
静态代理是因为对原来的方法不满意进行扩展的,但是他也没有 被代理的对象啊