以上就是MyBatis中的LRU缓存的机制了,自身维护了一个LinkedHashMap,开启了LRU机制,重写了removeEldestEntry方法,当大小触发阈值的时候维护最近最少使用的元素key,委托给组合进来的Cache对象移除,整个流程下来就使得被装饰着有了LRU的增强。
SoftCache一个软引用的MyBatisCache
弱引用弱引用比强引用稍弱一些。当JVM内存不足时,GC才会回收那些只被软引用指向的对象,从而避免OutOfMemoryError。当GC将只被软引用指向的对象全部回收之后,内存依然不足时,JVM才会抛出OutOfMemoryError。(这一特性非常适合做缓存,毕竟最终数据源在DB,还能保护JVM进程)
// 维护最近经常使用的缓存数据,该集合会使用强引用指向其中的每个缓存Value,防止被GC回收 private final Deque<Object> hardLinksToAvoidGarbageCollection; //与SortEntry对象关联,用于记录已经被回收的缓存条目 private final ReferenceQueue<Object> queueOfGarbageCollectedEntries; private final Cache delegate; //强引用的个数,默认256。即有256个热点数据无法直接被GC回收 private int numberOfHardLinks; public SoftCache(Cache delegate) { this.delegate = delegate; this.numberOfHardLinks = 256; this.hardLinksToAvoidGarbageCollection = new LinkedList<Object>(); this.queueOfGarbageCollectedEntries = new ReferenceQueue<Object>(); } @Override public void putObject(Object key, Object value) { // 同步删除已经被GC回收的Value removeGarbageCollectedItems(); delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries)); } private static class SoftEntry extends SoftReference<Object> { private final Object key; SoftEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) { // 关联引用队列。 // 当SoftReference指向的对象被回收的时候,JVM就会将这个SoftReference作为通知,添加到与其关联的引用队列 super(value, garbageCollectionQueue); this.key = key; } } @Override public Object getObject(Object key) { Object result = null; @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache SoftReference<Object> softReference = (SoftReference<Object>) delegate.getObject(key); // 委托获取缓存 if (softReference != null) { result = softReference.get(); if (result == null) { // 重要的一步!判断Value是否为空,为空则表示弱引用指向的对象已经被GC回收了,就需要同步删除该缓存。 delegate.removeObject(key); } else { // See #586 (and #335) modifications need more than a read lock // 读取缓存后,维护“强引用”的数据。 synchronized (hardLinksToAvoidGarbageCollection) { hardLinksToAvoidGarbageCollection.addFirst(result); // 将缓存添加进强引用队列(热点数据) if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { hardLinksToAvoidGarbageCollection.removeLast(); // 维护队列个数 } } } } return result; } @Override public Object removeObject(Object key) { removeGarbageCollectedItems(); // 删除被GC回收的Value return delegate.removeObject(key); // 委托删除缓存 } private void removeGarbageCollectedItems() { SoftEntry sv; // 引用关联的队列如果有值,则说明有被GC回收的Value while ((sv = (SoftEntry) queueOfGarbageCollectedEntries.poll()) != null) { delegate.removeObject(sv.key); } } WeakCache一个弱引用的MyBatisCache
与弱引用类似(基本相同),不过多介绍了。