开发者学堂课程【高校精品课-厦门大学 -JavaEE 平台技术:获得Mapper对象】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/80/detail/15949
获得Mapper对象
内容介绍:
一、绘制 Spring 动态模型结构图
二、动态结构图易错点分析
三、Spring 容器识别mapper对象
本节课学习动态模型,动态模型是在 Spring框架中间重要的一步,即 outwhile,是指在对象中定义了属性.....mapper。关于执行 outwhile的信息是如何被 Spring的容器获取到的呢?上面 Spring bean已经覆盖到了所有的配置,但其实际上并未实
例化出其他的对象,而是在执行outwhile时才真正地写入对象。
一、绘制Spring动态模型结构图
以下为动态模型结构图:
在定义了 outwhile时,框架通过 sqlsession对象——Default sqlsession(仅有一种sqlsession)找到要获取的 mapper的对象,并将其写入。
因为 sqlsession是使用 My batis的入口。因此要找 mapper也需要通sqlsession。
在 sqlsession的设计上,其提供了一个叫做 getMapper的方法,其传入参数type,
即接口的类(Java 反射机制的类),返回要建立的对象。
1、getMapper方法的实现
在该方法中间,可以看到数据一旦发生变化,就要读取配置信息,因为在启动时就
已经把配置信息囊括在内了。
在读取配置信息时,要读取 sqlsession中的一个属性 configuration。因此,一进入 sqlsession 就通过其属性 configuration 调用 getMapper(type,sqlsession)方法去获得 mapper对象。
因为其本身是个申请,并不知道获得的 mapper是什么,而我们知道 mapper是在
启动时就被囊括到 configuration的配置信息里,因此 configuration去使用getMapper 去获取该信息,这其实是最简单的信息专家的方式。并且此时getMapper 不仅只传入了type参数,而且还传入了 sqlsession,这里的 sqlsession其实是 sqlsession本身,在代码中体现为“this”,为了表述得更为清楚,就把前面的对象的名词定义为了 sqlsession,这是与代码不一致的地方,但是为了直观清楚地展现该过程,便将其名词进行了单独的定义。
2、configuration如何获取mapper
刚刚提到,所有的mapper信息都定义在 mapper Registry中,因此 configuration同样是使用信息专家的原则去获取 mapper。所以,在 configuration中,configuration又去 找mapper Registry去getMapper,传输的参数与之前相同(type,sqlsession)。
3、mapper Registry如何获取得mapper
mapper Registry 中有一个 Hashmap结构,名称为 knowmapper,指向其 mapper proxy factory,是所有内含的mapper。对于其接口,Map中有一个方法
GET,其存在返回值即为 MapperProxyFactory,key为type。
这样,就可以由从配置信息中获取的结构中得到接口的类型所对应的MapperProxyFactory 对象。获取到对象之后,再用该对象构造最终要进驻的对象。为了与代码保持一致,动态结构图中的变量名称也与代码中完全相同。
获得的 MapperProxyFactory对象再去调用 newInstance方法去构造目标的mapper,传输的为 sqlsession,因为这是与type
对应的 ProxyFactory,因此不需要再传输type,只要对其提出构造mapper的请。
4、newInstance如何构造mapper对象
传入的newInstance 方法实际上直接新建了一个 MapperProxy,在图上将该newInstance方法体现为 create,除传入 sqlsession之外,还传入了两个参数,一个是Mapperfactory,在 ProxyFactory中指向了定义的mapper的对象,而将该值放到map结构中时,不仅把它的 key值作为它的 key,而是将其属性也设为了它的key;另外一个参数是 method cache,其也是 MapperProxyFactory的另外一个属性,该属性已经指向了下面调用方法的 Invoke,同时调用方法的 Invoke也是map。因此 Mapperfactory与 method cache两个值的来源是 MapperProxyFactory 的属性,而 sqlsession则是由前面传输而来的。而前面对于 sqlsession 一步步的传输也正是为了构造 mapper时包含一个属性为 sqlsession。因为 mapper最终要执行的所有命令都要通过 sqlsession完成。
二、动态结构图易错点分析
在详细设计时,需要提供动态模型和静态模型,静态模型错误率较低,而动态模型
错误率较高,这写错误可能包含两种可能:
一种是事无巨细的编写代码,我们这里的动态模型结构图与源码有一定差异,因为源码中有很多判断语句的,如判断传入的参数是否合法,若传入的参数为空如何处理处理等,其中包含很多分支。而这里绘制结构图时为了更为清晰直观的讲明重点——如何获取Mapper以及理解各部分内容之间的协作,而不包含代码中的细节(如各种分支),故只是画出了源码中 Happy Paste的代码,而非所有的代码,但也尽量保持了与代码的一致性,如该图中所有的类名、属性名、变量名都与代码中
完全相同,就可以实现动态结构图与代码的准确对应。
除此之外,在手工画动态结构图时,还要保证图中所有的变量(包括返回值、对象的名称、局域的变量、传递的参数)都要有来源,要么来自于前面传输的内容,要么在静态图中有相应的属性,而不能凭空产生,否则无法判断推断逻辑的先后顺序,这一点与根据代码绘图不同。所以,再次强调一定注意所有的些变量名称要么是传入参数,要么是静态模型的属性,要么是中间某个部分的返回值,总之,一定
要与其来源相吻合。
三、Spring容器识别mapper对象
Spring 容器要注入 mapper时如何识别 mapper对象?结合上面绘制的结构图不难发现,其中放入的实际上是 MapperProxy对象,MapperProxy对象负责实现对于Mapper接口方法的调用。MapperProxy对象如何 Mapper接口方法?
结合动态结构图,可以发现其中大量使用了信息专家的原则,将职责一层层地向下传递,而不是做跨越性的调用。
就如连续使用 getMapper,这是因为 configuration也应该由 mapper Registry完成,故将它传给了 mapper Registry。也就是在设计过程使用信息专家的思想原则。