mybatis MyBatis缓存实现类
起因:在工作中常常要用到mybatis框架,如果对其执行流程不清楚的话,就会有一种出了bug不知道要去什么地方找的尴尬。本文为学习《Mybatis源码深度解析》后的总结。感谢江荣波的这本书。
1.MyBatis的缓存基于JVM堆内存实现
了解一下MyBatis缓存的实现原理。MyBatis的缓存基于JVM堆内存实现,即所有的缓存数据都存放在Java对象中。MyBatis通过Cache接口定义缓存对象的行为,Cache接口代码如下
Cache接口2.Cache接口中各个方法
getId():该方法用于获取缓存的Id,通常情况下缓存的Id为Mapper的命名空间名称。
putObject():该方法用于将一个Java对象添加到缓存中,该方法有两个参数,第一个参数为缓存的Key,即CacheKey的实例;第二个参数为需要缓存的对象。
getObject():该方法用于获取缓存Key对应的缓存对象。
removeObject():该方法用于将一个对象从缓存中移除。
clear():该方法用于清空缓存。
getReadWriteLock():该方法返回一个ReadWriteLock对象,该方法在3.2.6版本后已经不再使用。
3.Cache接口的实现类
MyBatis中的缓存类采用装饰器模式设计,Cache接口有一个基本的实现类,即PerpetualCache类,该类的实现比较简单,通过一个HashMap实例存放缓存对象。需要注意的是,PerpetualCache类重写了Object类的equals()方法,当两个缓存对象的Id相同时,即认为缓存对象相同。另外,PerpetualCache类还重写了Object类的hashCode()方法,仅以缓存对象的Id作为因子生成hashCode。
除了基础的PerpetualCache类之外,MyBatis中为了对PerpetualCache类的功能进行增强,提供了一些缓存的装饰器类,如图所示。
Mybatis缓存实现类4.Cache缓存装饰器类功能
-
BlockingCache:阻塞版本的缓存装饰器,能够保证同一时间只有一个线程到缓存中查找指定的Key对应的数据。
-
FifoCache:先入先出缓存装饰器,FifoCache内部有一个维护具有长度限制的Key键值链表(LinkedList实例)和一个被装饰的缓存对象,Key值链表主要是维护Key的FIFO顺序,而缓存存储和获取则交给被装饰的缓存对象来完成。
-
LoggingCache:为缓存增加日志输出功能,记录缓存的请求次数和命中次数,通过日志输出缓存命中率。
-
LruCache:最近最少使用的缓存装饰器,当缓存容量满了之后,使用LRU算法淘汰最近最少使用的Key和Value。LruCache中通过重写LinkedHashMap类的removeEldestEntry()方法获取最近最少使用的Key值,将Key值保存在LruCache类的eldestKey属性中,然后在缓存中添加对象时,淘汰eldestKey对应的Value值。具体实现细节读者可参考LruCache类的源码。
-
ScheduledCache:自动刷新缓存装饰器,当操作缓存对象时,如果当前时间与上次清空缓存的时间间隔大于指定的时间间隔,则清空缓存。清空缓存的动作由getObject()、putObject()、removeObject()等方法触发。
-
SerializedCache:序列化缓存装饰器,向缓存中添加对象时,对添加的对象进行序列化处理,从缓存中取出对象时,进行反序列化处理。
-
SoftCache:软引用缓存装饰器,SoftCache内部维护了一个缓存对象的强引用队列和软引用队列,缓存以软引用的方式添加到缓存中,并将软引用添加到队列中,获取缓存对象时,如果对象已经被回收,则移除Key,如果未被回收,则将对象添加到强引用队列中,避免被回收,如果强引用队列已经满了,则移除最早入队列的对象的引用。
-
SynchronizedCache:线程安全缓存装饰器,SynchronizedCache的实现比较简单,为了保证线程安全,对操作缓存的方法使用synchronized关键字修饰。
-
TransactionalCache:事务缓存装饰器,该缓存与其他缓存的不同之处在于,TransactionalCache增加了两个方法,即commit()和rollback()。当写入缓存时,只有调用commit()方法后,缓存对象才会真正添加到TransactionalCache对象中,如果调用了rollback()方法,写入操作将被回滚。
-
WeakCache:弱引用缓存装饰器,功能和SoftCache类似,只是使用不同的引用类型。
4.PerpetualCache类及MyBatis提供了缓存装饰类的使用案例
如上面的代码所示,我们可以使用MyBatis提供的缓存装饰器类对基础的PerpetualCache类的功能进行增强,使用不同的装饰器后,缓存对象则拥有对应的功能。
另外,MyBatis提供了一个CacheBuilder类,通过生成器模式创建缓存对象。下面是使用CacheBuilder构造缓存对象的案例:
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!