通常为了减轻数据库的压力,我们会引入缓存。在Dao查询数据库之前,先去缓存中找是否有要找的数据,如果有则用缓存中的数据即可,就不用查询数据库了。如果没有才去数据库中查找。这样就能分担一下数据库的压力。另外,为了让缓存中的数据与数据库同步,我们应该在该数据发生变化的地方加入更新缓存的逻辑代码。这样无形之中增加了工作量,同时也是一种对原有代码的入侵。这对于有着代码洁癖的程序员来说,无疑是一种伤害。 MyBatis框架早就考虑到了这些问题,因此MyBatis提供了自定义的二级缓存概念,方便引入我们自己的缓存机制,而不用更改原有的业务逻辑。下面就让我们了解一下MyBatis的缓存机制。
正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持;
接下来将结合 MyBatis 序列图进行源码分析。在分析其Cache前,先看看其整个处理过程。
Executor:执行器接口。也是最终执行数据获取及更新的实例。其结构如下:
一级缓存和二级缓存很相似,都是实现Cache缓存接口,然后等待调用。其中的一级缓存具体实现其实使用了Map存储,原理非常简单。PerPetualCache具体结构如下:
像之前所说,Cache是一个缓存接口,运行时用到的其实是在解析mapper文件的时候根据配置文件生成的对应Cahce实现类。另外这个实现类的构造过程使用了建造者(Builder)模式。在build的过程中,将所有设计到的cache放入基础缓存中,并使用装饰器模式将cache进行装饰。具体设计如下:
1. 从配置文件中获取节点,将配置信息提取出来初始化生成Cache
2. useNewCache方法中使用了建造者(Builder)模式,将从配置文件中读取出来的各个元素组装起来。其中最主要的是build方法。
3. 在build方法中,值得注意的是使用了装饰器模式,将几个基本的Cache装饰了一下。因为我们的Cache只是加入了自定义的缓存功能和逻辑,日志功能、同步功能等其实并没有。所以需要装饰一下,具体代码如下:
4. 最终的缓存实例对象结构:
总体上看,我们可以把MyBatis关于缓存的这一部分分为三个部分:
MyBatis的整体思路其实很简单,但是跟着源码发现,一个好的框架需要考虑的问题很多,从可扩展性、功能维护等角度考虑,如果没有一个好的设计思路会把代码设计的很乱很乱。MyBatis充分利用了动态代理、建造模式、装饰器模式,似的他们结合在一起,让整个框架变得简单易用,其实是很难得的。 这就好比读一本书,需要先读后再度薄一样,框架的设计最开始需要考虑到各种各样的问题,然后把一个简单的思路变得复杂。然后通过合理的设计,将复杂的问题简单的设计出来,使得代码很整洁,易于维护和读,这才是一个好的框架应该有的样子。 真的很感谢能有这么一个机会研究一下mybatis,并从中学到了许多。希望有朝一日,也能写出想mybatis一样的框架。 在这里很非常感谢http://denger.iteye.com/blog/1126423/。