mybatis 缓存
- Author: HuiFer
- Description: 该文介绍 mybatis Cache 源码
源码阅读工程: SourceHot-Mybatis
org.apache.ibatis.cache.Cache
public interface Cache {String getId();/*** 放入数据*/void putObject(Object key, Object value);/*** 获取数据*/Object getObject(Object key);/*** 移除数据*/Object removeObject(Object key);/*** 清空数据*/void clear();/*** 有多少缓存数据*/int getSize();/*** 重入锁* @return A ReadWriteLock*/default ReadWriteLock getReadWriteLock() {return null;}}
- BlockingCache: 阻塞的缓存
- FifoCache: 按对象进入缓存的顺序来移除它们。
- LruCache: 最近最少使用的:移除最长时间不被使用的对象。
- SoftCache: 软引用:移除基于垃圾回收器状态和软引用规则的对象
- WeakCache: 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
BlockingCache
- BlockingCache 内部使用了
ReentrantLock来进行加锁开锁这个操作.在插入缓存时上锁,插入缓存后释放.请求缓存值得时候同理
public class BlockingCache implements Cache {private final Cache delegate;/*** 线程安全的map*/private final ConcurrentHashMap<Object, ReentrantLock> locks;private long timeout;public BlockingCache(Cache delegate) {this.delegate = delegate;this.locks = new ConcurrentHashMap<>();}@Overridepublic String getId() {return delegate.getId();}@Overridepublic int getSize() {return delegate.getSize();}@Overridepublic void putObject(Object key, Object value) {try {delegate.putObject(key, value);} finally {releaseLock(key);}}@Overridepublic Object getObject(Object key) {acquireLock(key);Object value = delegate.getObject(key);if (value != null) {// 释放锁releaseLock(key);}return value;}@Overridepublic Object removeObject(Object key) {// despite of its name, this method is called only to release locksreleaseLock(key);return null;}@Overridepublic void clear() {delegate.clear();}private ReentrantLock getLockForKey(Object key) {return locks.computeIfAbsent(key, k -> new ReentrantLock());}/*** 请求锁* @param key*/private void acquireLock(Object key) {Lock lock = getLockForKey(key);if (timeout > 0) {try {// 上锁boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);if (!acquired) {throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId());}} catch (InterruptedException e) {throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e);}} else {lock.lock();}}/*** 释放锁* @param key*/private void releaseLock(Object key) {ReentrantLock lock = locks.get(key);if (lock.isHeldByCurrentThread()) {lock.unlock();}}public long getTimeout() {return timeout;}public void setTimeout(long timeout) {this.timeout = timeout;}}
FifoCache
- 存储结构是
java.util.LinkedList
public class FifoCache implements Cache {private final Cache delegate;/*** 队列*/private final Deque<Object> keyList;private int size;public FifoCache(Cache delegate) {this.delegate = delegate;this.keyList = new LinkedList<>();this.size = 1024;}@Overridepublic String getId() {return delegate.getId();}@Overridepublic int getSize() {return delegate.getSize();}public void setSize(int size) {this.size = size;}@Overridepublic void putObject(Object key, Object value) {cycleKeyList(key);delegate.putObject(key, value);}@Overridepublic Object getObject(Object key) {return delegate.getObject(key);}@Overridepublic Object removeObject(Object key) {return delegate.removeObject(key);}@Overridepublic void clear() {delegate.clear();keyList.clear();}/*** 添加 key 删除最开始的一个** @param key*/private void cycleKeyList(Object key) {keyList.addLast(key);if (keyList.size() > size) {Object oldestKey = keyList.removeFirst();delegate.removeObject(oldestKey);}}}
LruCache
- 存储结构是
java.util.LinkedHashMap
/*** Lru (least recently used) cache decorator.* LRU 緩存策略 最近最少使用的:移除最长时间不被使用的对象。** @author Clinton Begin*/public class LruCache implements Cache {private final Cache delegate;/*** {@link LinkedHashMap}*/private Map<Object, Object> keyMap;private Object eldestKey;public LruCache(Cache delegate) {this.delegate = delegate;setSize(1024);}@Overridepublic String getId() {return delegate.getId();}@Overridepublic int getSize() {return delegate.getSize();}/*** 设置大小** @param size*/public void setSize(final int size) {keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {private static final long serialVersionUID = 4267176411845948333L;@Overrideprotected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {// 数量超出预设值 执行boolean tooBig = size() > size;if (tooBig) {// 获取被移除的keyeldestKey = eldest.getKey();}return tooBig;}};}@Overridepublic void putObject(Object key, Object value) {delegate.putObject(key, value);cycleKeyList(key);}@Overridepublic Object getObject(Object key) {keyMap.get(key); //touchreturn delegate.getObject(key);}@Overridepublic Object removeObject(Object key) {return delegate.removeObject(key);}@Overridepublic void clear() {delegate.clear();keyMap.clear();}/*** 删除最早的一个key* @param key*/private void cycleKeyList(Object key) {keyMap.put(key, key);if (eldestKey != null) {delegate.removeObject(eldestKey);eldestKey = null;}}}
