mybatis-cache包阅读

cache包主要功能

  • 一级缓存:一级本地缓存都是PerpetualCache类型,保存在BaseExecutor执行器,而执行器又在SqlSession中,所以一级缓存的生命周期与SqlSession相同,除非指定一级缓存范围为STATEMENT
  • 二级缓存:二级自定义缓存,实现了Cache接口的类都可以作为二级缓存,所以还可配置第三方缓存。二级缓存以namespace名称空间为其唯一标识,被保存在Configuration核心配置对象中,CachingExecutor执行器就是用来处理二级缓存的执行器。

cache包主要结构

mybatis-cache包阅读_第1张图片

cache包设计模式

  • 装饰设计模式:通过这些装饰器来实现所需功能:回收策略、日志记录、定时刷新等等。但是无论怎么装饰,经过多少层装饰,最后使用的还是基本的实现类PerpetualCache。
  • SoftCache:利用JDK的SoftReference软引用,借助垃圾回收器进行缓存对象的回收。
  • WeakCache:与SoftCache几乎相同,只是把软引用换成了弱引用。
  • 弱引用缓存代码:
/**
 * Weak Reference cache decorator.
 * Thanks to Dr. Heinz Kabutz for his guidance here.
 *
 * @author Clinton Begin
 */
public class WeakCache implements Cache {
  //为了阻止value被回收声明的队列
  private final Deque<Object> hardLinksToAvoidGarbageCollection;
  //ReferenceQueue可以完成,当一个obj被gc掉之后,其相应的包装类,即ref对象会被放入queue中。我们可以从queue中获取到相应的对象信息,同时进行额外的处理。比如数据清理等
  private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
  private final Cache delegate;
  private int numberOfHardLinks;
 
  public WeakCache(Cache delegate) {
    this.delegate = delegate;
    this.numberOfHardLinks = 256;
    this.hardLinksToAvoidGarbageCollection = new LinkedList<>();
    this.queueOfGarbageCollectedEntries = new ReferenceQueue<>();
  }
 
  @Override
  public String getId() {
    return delegate.getId();
  }
 
  @Override
  public int getSize() {
    removeGarbageCollectedItems();
    return delegate.getSize();
  }
 
  public void setSize(int size) {
    this.numberOfHardLinks = size;
  }
 
  @Override
  public void putObject(Object key, Object value) {
    removeGarbageCollectedItems();
    delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries));
  }
 
  @Override
  public Object getObject(Object key) {
    Object result = null;
    @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache
    WeakReference<Object> weakReference = (WeakReference<Object>) delegate.getObject(key);
    if (weakReference != null) {
      result = weakReference.get();
      if (result == null) {
        delegate.removeObject(key);
      } else {
        //用一个强引用队列指向value,这样阻止了被回收,阻止被回收的大小是numberOfHardLinks
        hardLinksToAvoidGarbageCollection.addFirst(result);
        if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
          hardLinksToAvoidGarbageCollection.removeLast();
        }
      }
    }
    return result;
  }
 
  @Override
  public Object removeObject(Object key) {
    removeGarbageCollectedItems();
    return delegate.removeObject(key);
  }
 
  @Override
  public void clear() {
    hardLinksToAvoidGarbageCollection.clear();
    removeGarbageCollectedItems();
    delegate.clear();
  }
 
  private void removeGarbageCollectedItems() {
    WeakEntry sv;
    //利用ReferenceQueue清理 无用的弱引用对象
    while ((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) != null) {
      delegate.removeObject(sv.key);
    }
  }
 
  private static class WeakEntry extends WeakReference<Object> {
    private final Object key;
 
    private WeakEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
      super(value, garbageCollectionQueue);
      this.key = key;
    }
  }
  • 附上源码结构:
  • 好文链接:
    https://www.cnblogs.com/wuzhenzhao/p/11103043.html
    http://blog.csdn.net/kavendb/article/details/5935577
    mybatis-cache包阅读_第2张图片

你可能感兴趣的:(源码阅读,mybatis,cache,一级缓存,二级缓存)