mybatis源码3-二级缓存

2019-01-19  本文已影响0人  modou1618

一 配置

private void cacheElement(XNode context) throws Exception {
  if (context != null) {
    String type = context.getStringAttribute("type", "PERPETUAL");
    Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
    String eviction = context.getStringAttribute("eviction", "LRU");
    Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
    Long flushInterval = context.getLongAttribute("flushInterval");
    Integer size = context.getIntAttribute("size");
    boolean readWrite = !context.getBooleanAttribute("readOnly", false);
    Properties props = context.getChildrenAsProperties();
    builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, props);
  }
}

二 初始化

2.1 cache创建CacheBuilder.build()

private void setDefaultImplementations() {
  if (implementation == null) {
// implementation表示存储类型,默认PerpetualCache是内存map存储。
    implementation = PerpetualCache.class;
    if (decorators.size() == 0) {
//decorators表示过期策略,默认LruCache是最近最少使用过期策略
      decorators.add(LruCache.class);
    }
  }
}

2.1.1 PerpetualCache类型处理

if (PerpetualCache.class.equals(cache.getClass())) { // issue #352, do not apply decorators to custom caches
  for (Class<? extends Cache> decorator : decorators) {
    cache = newCacheDecoratorInstance(decorator, cache);
    setCacheProperties(cache);
  }
  cache = setStandardDecorators(cache);
}

private Cache setStandardDecorators(Cache cache) {
  try {
    MetaObject metaCache = SystemMetaObject.forObject(cache);
    if (size != null && metaCache.hasSetter("size")) {
      metaCache.setValue("size", size);
    }
    if (clearInterval != null) {
      cache = new ScheduledCache(cache);
      ((ScheduledCache) cache).setClearInterval(clearInterval);
    }
    if (readWrite) {
      cache = new SerializedCache(cache);
    }
    cache = new LoggingCache(cache);
    cache = new SynchronizedCache(cache);
    return cache;
  } catch (Exception e) {
    throw new CacheException("Error building standard cache decorators.  Cause: " + e, e);
  }
}

2.1.2 其他类型处理

2.2 cache缓存

2.3 缓存代理

2.3.1 LruCache

keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
  private static final long serialVersionUID = 4267176411845948333L;

  protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
    boolean tooBig = size() > size;
    if (tooBig) {
      eldestKey = eldest.getKey();
    }
    return tooBig;
  }
};

2.3.2 ScheduledCache

2.3.3 ScheduledCache

2.3.4 LoggingCache

2.3.5 SynchronizedCache

三 使用

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
    throws SQLException {
  Cache cache = ms.getCache();
  if (cache != null) {
    flushCacheIfRequired(ms);
    if (ms.isUseCache() && resultHandler == null) {
      ensureNoOutParams(ms, parameterObject, boundSql);
      @SuppressWarnings("unchecked")
      List<E> list = (List<E>) tcm.getObject(cache, key);
      if (list == null) {
        list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
        tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
      }
      return list;
    }
  }
  return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

3.1 TransactionalCacheManager

3.2 TransactionalCache

public void putObject(Object key, Object object) {
  entriesToRemoveOnCommit.remove(key);
  entriesToAddOnCommit.put(key, new AddEntry(delegate, key, object));
}

public Object removeObject(Object key) {
  entriesToAddOnCommit.remove(key);
  entriesToRemoveOnCommit.put(key, new RemoveEntry(delegate, key));
  return delegate.getObject(key);
}
public void commit() {
  if (clearOnCommit) {
    delegate.clear();
  } else {
    for (RemoveEntry entry : entriesToRemoveOnCommit.values()) {
      entry.commit();
    }
  }
  for (AddEntry entry : entriesToAddOnCommit.values()) {
    entry.commit();
  }
  reset();
}
private void reset() {
  clearOnCommit = false;
  entriesToRemoveOnCommit.clear();
  entriesToAddOnCommit.clear();
}
上一篇 下一篇

猜你喜欢

热点阅读