带你彻底搞懂MyBatis的底层实现之缓存模块(Cache)-吊打面试官必备技能

本文详细介绍了MyBatis的缓存机制,包括PerpetualCache、装饰器模式下的Cache实现,如BlockingCache,以及缓存的应用。在一级缓存层面,探讨了SqlSession中的LocalCache工作原理,分析了如何在不同场景下使用和测试一级缓存,强调了其在不同Session中的行为差异。此外,文章还提到了二级缓存和缓存配置的相关内容。
摘要由CSDN通过智能技术生成

return false;

}

Cache otherCache = (Cache) o;

// 只关心ID

return getId().equals(otherCache.getId());

}

@Override

public int hashCode() {

if (getId() == null) {

throw new CacheException(“Cache instances require an ID.”);

}

// 只关心ID

return getId().hashCode();

}

}

然后我们可以来看看cache.decorators包下提供的装饰器。他们都实现了Cache接口。这些装饰器都在PerpetualCache的基础上提供了一些额外的功能,通过多个组合实现一些特殊的需求。

3 BlockingCache


通过名称我们能看出来是一个阻塞同步的缓存,它保证只有一个线程到缓存中查找指定的key对应的数据。

public class BlockingCache implements Cache {

private long timeout; // 阻塞超时时长

private final Cache delegate; // 被装饰的底层 Cache 对象

// 每个key 都有对象的 ReentrantLock 对象

private final ConcurrentHashMap<Object, ReentrantLock> locks;

public BlockingCache(Cache delegate) {

// 被装饰的 Cache 对象

this.delegate = delegate;

this.locks = new ConcurrentHashMap<>();

}

@Override

public String getId() {

return delegate.getId();

}

@Override

public int getSize() {

return delegate.getSize();

}

@Override

public void putObject(Object key, Object value) {

try {

// 执行 被装饰的 Cache 中的方法

delegate.putObject(key, value);

} finally {

// 释放锁

releaseLock(key);

}

}

@Override

public Object getObject(Object key) {

acquireLock(key); // 获取锁

Object value = delegate.getObject(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();

}

private ReentrantLock getLockForKey(Object key) {

return locks.computeIfAbsent(key, k -> new ReentrantLock());

}

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();

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值