mybatis之缓存模块
Posted 我爱看明朝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis之缓存模块相关的知识,希望对你有一定的参考价值。
mybatis之缓存模块
mybatis中存在一级(默认开启)、二级缓存。缓存可以加快查询速度,减少连接db的次数。
cache模块属于mybatis的基础支持层。位于org.apache.ibatis.cache包下。
--------org.apache.ibatis.cache
-------------------------------decorators
-----------------------------------------BlockingCache
-----------------------------------------FifoCache
-----------------------------------------LoggingCache
-----------------------------------------LruCache
-----------------------------------------ScheduledCache
-----------------------------------------SerializedCache
-----------------------------------------SoftCache
-----------------------------------------SynchronizedCache
-----------------------------------------TransactionalCache
-----------------------------------------WeakCache
-------------------------------impl
-----------------------------------PerpetualCache
------------------------------Cache
Cache
缓存的顶级接口
public interface Cache {
// 得到缓存的id
String getId();
// 插入缓存
void putObject(Object key, Object value);
// 查询到缓存
Object getObject(Object key);
// 删除缓存
Object removeObject(Object key);
//清理这个缓存实例
void clear();
// 这个方法可选,不是核心调用方法,查询缓存key的个数
int getSize();
//
ReadWriteLock getReadWriteLock();
}
PerpetualCache
缓存的基础实现(实现了基本的缓存功能,底层数据结构使用HashMap)
一级缓存是会话级别的缓存(SqlSession)。
public class PerpetualCache implements Cache {
private final String id;
// 存储缓存底层数据结构使用hashMap
private Map<Object, Object> cache = new HashMap<Object, Object>();
// 传入
public PerpetualCache(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public int getSize() {
return cache.size();
}
// 插入缓存
@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();
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
@Override
public boolean equals(Object o) {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
if (this == o) {
return true;
}
if (!(o instanceof Cache)) {
return false;
}
Cache otherCache = (Cache) o;
return getId().equals(otherCache.getId());
}
@Override
public int hashCode() {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
return getId().hashCode();
}
}
BlockingCache
BlockingCache是带有阻塞功能的缓存装饰器。
public class BlockingCache implements Cache {
//超时时间
private long timeout;
// 被装饰的缓存
private final Cache delegate;
// 每一个Key拥有一把可重入锁
private final ConcurrentHashMap<Object, ReentrantLock> locks;
//构造器,装饰其他cache对象
public BlockingCache(Cache delegate) {
this.delegate = delegate;
this.locks = new ConcurrentHashMap<Object, ReentrantLock>();
}
@Override
public String getId() {
return delegate.getId();
}
@Override
public int getSize() {
return delegate.getSize();
}
// 插入Key的缓存,插入完毕同时释放锁
@Override
public void putObject(Object key, Object value) {
try {
delegate.putObject(key, value);
} finally {
releaseLock(key);
}
}
// 查询key的缓存
@Override
public Object getObject(Object key) {
//获取到key的锁
acquireLock(key);
// 查询key缓存的值
Object value = delegate.getObject(key);
//如果value不为null,则释放锁,返回值,否则一直持有锁,知道key有值插入到缓存
if (value != null) {
releaseLock(key);
}
return value;
}
@Override
public Object removeObject(Object key) {
// despite of its name, this method is called only to release locks
releaseLock(key);
return null;
}
@Override
public void clear() {
delegate.clear();
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
//查询Key持有的锁,如果没有则创建新锁
private ReentrantLock getLockForKey(Object key) {
ReentrantLock lock = new ReentrantLock();
ReentrantLock previous = locks.putIfAbsent(key, lock);
return previous == null ? lock : previous;
}
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();
}
}
private void releaseLock(Object key) {
ReentrantLock lock = locks.get(key);
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
带你彻底搞懂MyBatis的底层实现之缓存模块(Cache)-吊打面试官必备技能