接着Mybatis底层分析(一)开始继续追进,建议对比(一)中的内容看这篇文章。
为什么分开来写文章?因为一篇文章分析内容太长了,看到结尾就忘记之前代码了,可方便读者可另开一个窗口阅读代码。废话不多说,开始追进...
追进parser.parse()方法
这里的箭头赋值的属性,在文章(一)中已经解释过,这里的话evalNode()方法里面也比较复杂,不想上图解释了,只需要知道做的事是把xml文件转换成了一个Xnode类返回了(读者感兴趣可以自己追进去,个人建议debug) 追进parseConfiguration()方法
这块主要看解析 mappers 属性的方法,这一块会解答你的一个疑问?为什么我们平时开发的时候,mapper接口没有实现类,却可以注入,并且可以直接使用接口方法呢?
这里parent 的值可以理解为节点<mappers>,而<package>是他的子节点,这里注意的是configuration这个属性是其父类BaseBuilder 里的,而且已经在 文章(一)中赋值了,下面
追进addMappers()方法
这里又调用,继续追进
再调用,这块追进 new ResolverUtil.IsA(superType)
可以看到 IsA 是 ResolverUtil 的静态内部类,且给parent 属性赋值为 Object.class
下面回过头来继续追进 resolverUtil.find(..)
追进 getPackagePath(..)
这其实就是把 org.mybatis.builder 格式转换为 org/mybatis/builder
这里VFS方法也很复杂,展开讲这篇文章,可能又写不完了。。有兴趣的可以自己追进去看,不过这块也很容易推测出来这块代码,其实就是把<mappers> <name>属性值 包下面路径的所有.class文件 生成一个List 集合,下面for循环再继续遍历,追进 addIfMatching(..)
Class<?> type = loader.loadClass(externalName) 类加载,追进 test.matches(..)
再 追进 isAssignableFrom(..)
可以看到这个方法是 native 修饰,代表此方法非java所写,所以这里最简单的方法就是反推,或者翻译注释。英文差的直接选择反推
这一块如果返回false就不会执行了,我们假设它能走通?继续走一下代码
往 HashSet 里存放 Class ,for循环完成,下图箭头方法就追进完成了
追进 getClasses()
发现 返回的就是刚刚储存Class 的HashSet,下面追进for循环 里的addMapper(mapperClass)
这一块我相信,看名字应该能知道方法是干嘛的了吧?马上开始生成动态代理了。来波回忆杀?HR:你怎么理解spring? aop ioc?生成动态代理必须实现 InvocationHanderler接口?我相信如果没有探究框架底层的话,你会产生疑问?动态代理开发中用到了吗?哪里用的?下篇文章将探究动态代理在框架中的应用..卖个关子哈哈