整体架构
在把mybatis源码下载编译好成自己的模块时,就可以随心的加入一些注释。下面对其整体架构进行简单分析。
mybatis一共有16个包。其实比较核心的模块也就几个,其他的都是用于辅助,锦上添花的。
16个模块很多都是一眼就看出负责什么的。例如datasouce
肯定就是数据源模块;logging
就是负责日志的;cache
负责缓存模块;transaction
负责事务相关;annotations
负责基于注解的开发映射;executor
则是执行器…
每个模块具体的功能如下。
前面的话,个人觉得不需要每个模块都搞明白。选择一些有代表性的模块来看看作者的设计理念
和设计模式的运用
就差不多了。
逻辑分层
了解了所有的包模块,还需要对其的分工进行大致的归属和了解。
其实分层的目的主要是为了把同一职责的功能模块放到一起,比较好去维护
。像我们常用的MVC分层以及service
、dao
、controller
(MVC = model view controller),都是将同一职责的模块放到一起。
dao层就专注于数据库的交互进行数据处理;service主要是项目业务逻辑的处理等;controller则是处理前端请求;model模型用于封装实体;view用于页面的渲染展示…
而在mybatis也可以进行逻辑分层
,各个包之间还是平级关系,只不过对其进行简单的逻辑划分,便于理解功能。
mybatis简单逻辑分层
可以看到mybatis逻辑分层一般分三层即可。
基础支撑层:用于与数据库的交互。像数据源,资源加载,解析器这些都是直接跟数据库打交道的;而日志等用于辅助基础支撑。
核心处理层:就是mybatis自身的业务处理了。将传入的参数进行映射,对SQL语句进行解析,将底层查询到的数据结果进行封装等。
接口层:最上层了,也就是离用户最近
的一个模块,就对外提供服务了。
这也体现出了mybatis的门面模式
。
我们在使用的时候根本就不需要关心内部之间怎么调用的,只需要操作sqlsession
来读取数据库的数据并封装成实体对象。因为整个过程(读数据,封装成实体类对象)都是由mybatis内部去完成,我们不需要依赖其对应的类,大大降低的类与类之间的耦合程度。
日志模块
对整个模块进行了大概概括,下面需要对某个模块进行简单的了解。
单模块分析
在我们使用mybatis对数据库进行操作的时候,控制台都会打印对应的日志
下面来看看这个辅助功能是如何完成的。
首先,日志的的实现有很多。sl4j
、log4j
、log4j2
…
既然mybatis是个框架,那么肯定会对日志都进行一个适配,我们来看其源码
果然,提供了一个接口。其他具体的实现不需要过多的关心,在调用的时候只需要调用接口即可。即面向接口编程
用log4j进行举例。
我们只需要调用log接口的相应方法,如果是log4j实现,那么会组合一个log4j的对象,内部的实现交由这个对象去完成。
这样一来,不管底层装配什么日志框架,mybatis其他模块永远都是通过这个Log接口来调用,内部的具体实现还是由装配的日志框架完成。即使以后新增了其他的日志框架,只需要让其去适配
我们的日志模块即可。
mybatis在日志这一块就很好的运用了适配器模式
,就是便于对扩展开方,修改关闭
的开闭原则的最佳实践。
另外,关于日志的装配
mybatis自定义优先级
进行逐一装配。
最高优先级的不存在那就换次级的,逐级递减,代码很好理解
类加载时即执行装配,并且最后一层采用了NoLogging
进行适配,即没有引入任何的日志框架(一般不会执行到这部,因为有JDK的日志挡着)
装配的实现也很好理解,如果不存在就装配,存在啥都不做
我们自己在处理业务的时候,对于优先级加载
的问题也可以参考mybatis的这段实现,提供了一个不错的思路。
其他模块的引用
对模块分析完了以后,我们反过来看其他模块是如何运用的。
这里是需要对mybatis的执行流程有所了解才知道具体的调用,如果刚开始看的话。可以保留这个疑问,后期在看源码流程的时候就会明白在哪一块进行调用。
在SimpleExecutor
这个类中可以找到其调用
走到这里,已经可以大概了解了。
mybatis其他模块对日志的使用是通过动态代理
的方式进行一个功能加强,不会干预原有的业务,只是对其进行日志的增强处理。
我们看到其handler处理类就是他自己(ConnectionLogger),那么我们在这个类中找的invoke方法看是如何增强的
仔细捋一下大概就是如下内容:
- 我只增强对应的方法
- 执行完对应的方法后,返回statement对象;我也对statement对象进行日志的增强
小结
在阅读源码的过程中,需要对相应的设计模式
有所了解。尤其是动态代理,源码中都比较喜欢使用动态代理的方式对方法进行增强的操作。
另外,对单个模块的模式需要对整个流程有个大致的了解。
不然也可以通过找到这个方法被哪一个方法调用过,逐级往上调整可以发现模块是如何被调用的。但是这样的话,便于对流程的一个理解。