MyBatis缓存类PerpetualCache深度分析
计算机有两大基本的功能:计算和存储。在存储方面,缓存的设计和实现也是一门学问。这门学问里面包含什么门道呢?不妨研究一下MyBatis缓存类PerpetualCache,一定会大有收获的。
在MyBatis里面,存在一个PerpetualCache,它是一级缓存、二级缓存的最基本实现,但PerpetualCache只不过包装了一下HashMap。Perpetual是"永久、不间断"之意,以PerpetualCache为根本,在cache.decorators包里面有多种缓存的代理,实现了各种清除策略。
1、PerpetualCache 名字的含义
Perpetual是"永久、不间断"之意,为什么这么命名呢?稍加联系,便能明白。缓存的设计有两个重点问题:如何存储数据和采用何种清除策略。存储的话,用哈希表即可完美解决。对于清除策略而言,往往有多种选择。MyBatis作者Clinton Begin选择Perpetual来命名缓存,暗示这是一个最底层的缓存,数据一旦存储进来,永不清除,如果实现清除策略,请把Perpetual包装一下。在cache.decorators包里面有多种缓存,它们内部串联的主线就是按照“不同的清除策略”来贯穿的。
2、PerpetualCache的实现原理:
PerpetualCache仅仅是包装了HashMap,代码如下所示:
public class PerpetualCache implements Cache
{
private final String id;
private Map<Object, Object> cache = new HashMap<Object, Object>();
}
PerpetualCache的读取数据,也是通过内部的HashMap来实现的,代码如下所示:
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public Object getObject(Object key) {
return cache.get(key);
}
@Override
public Object removeObject(Object key) {
return cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
3、Key的设计:CacheKey
在PerpetualCache内部使用的Java自带的HashMap:
Map<Object, Object> cache = new HashMap<Object, Object>();
但是,HashMap的Key设计略显单薄,无法适应复杂的缓存场景,需要进行自定义设计。MyBatis实现了CacheKey类,其功能非常的强大。
public class CacheKey implements Cloneable, Serializable
{
private final int multiplier;
private int hashcode;
private long checksum;
private int count;
private List<Object> updateList;
}
代码分析如下所示:
(1)hashcode,用于表示CacheKey的哈希码
(2)checksum,总和校验,当出现复合key的时候,分布计算每个key的哈希码,然后求总和
(3)count,当出现复合key的时候,计算key的总个数
(4)updateList,当出现复合key的时候,保存每个key
CacheKey这个类设计的非常好,个人推荐感兴趣的人可以仔细读一读其源码。其初始化的过程如下所示:
public CacheKey(Object[] objects)
{
this();
updateAll(objects);
}
public void updateAll(Object[] objects)
{
for (Object o : objects)
{
update(o);
}
}
public void update(Object object)
{
int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);
count++;
checksum += baseHashCode;
baseHashCode *= count;
hashcode = multiplier * hashcode + baseHashCode;
updateList.add(object);
}
个人觉得PerpetualCache深度分析可以讲讲清理和put的情况。