shz.core.cache.CacheManager Maven / Gradle / Ivy
package shz.core.cache;
import shz.core.NullHelp;
import shz.core.PRException;
import shz.core.msg.ServerFailureMsg;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class CacheManager {
/**
* 是否查询操作
*/
protected abstract boolean isGet(CacheParam param);
/**
* 判断key是否被设置为null标识
*/
protected abstract boolean isNull(CacheParam param);
/**
* 获取缓存
*/
protected abstract Object get(CacheParam param);
/**
* 匹配缓存
*/
protected abstract boolean notMatch(CacheParam param);
/**
* 剩余时间
*/
protected long ttlMillis(CacheParam param) {
return 0L;
}
/**
* 刷新缓存
*/
protected void refresh(CacheParam param) {
}
/**
* 将该key设置为可能是null标识(注意此方法的实现需要保证线程安全)
*/
protected abstract boolean setPossibleNull(CacheParam param);
/**
* 设置为可能是null标识未成功进入等待
*/
protected void await(CacheParam param) {
CountDownLatch latch = new CountDownLatch(1);
try {
latch.await(param.timeoutMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
}
}
/**
* 将该key设置为 null标识
*/
protected abstract void setNull(CacheParam param);
/**
* 移除key的可能是null标识
*/
protected void removePossibleNull(CacheParam param) {
}
/**
* 在finally块中执行,即执行了目标方法后需操作(设置及删除缓存操作)
*
* @param response 目标方法返回值,这个值一般用来设置为缓存
*/
protected abstract void after(CacheParam param, Object response);
public final T execute(CacheParam cacheParam, Supplier supplier) {
if (cacheParam == null) return supplier.get();
boolean possible = false;
T response = null;
//查询操作
if (isGet(cacheParam)) {
//过滤器优先匹配,判断是否null标识
if (notMatch(cacheParam) || isNull(cacheParam)) return null;
//获取缓存
response = (T) get(cacheParam);
if (NullHelp.nonEmpty(response)) {
long ttlMillis;
if (cacheParam.time > 0L
&& cacheParam.ttlRefreshMillis > 0L
&& (ttlMillis = ttlMillis(cacheParam)) > 0L
&& ttlMillis <= cacheParam.ttlRefreshMillis) refresh(cacheParam);
return response;
}
//缓存失效或者误判,设置可能 null标识(一种中间状态),设置成功就去查数据库
if (!(possible = setPossibleNull(cacheParam))) {
//没有设置成功等待
await(cacheParam);
//再次判断(上一个线程可能查完了数据库,最终可能判断这个key为null标识)
if (isNull(cacheParam)) return null;
//再次获取
response = (T) get(cacheParam);
if (NullHelp.nonEmpty(response)) return response;
//出现这种情况,可能上一个线程设置缓存失败,也可能是出现异常
//如果是设置缓存失败,说明查询过数据库,继续执行数据库查询
if (!(possible = setPossibleNull(cacheParam))) return null;
}
}
try {
//执行目标方法
response = supplier.get();
return response;
} catch (Throwable t) {
throw PRException.of(t);
} finally {
try {
after(cacheParam, response);
} finally {
if (possible) {
try {
//数据库没查到,则设置null标识
if (NullHelp.isEmpty(response)) setNull(cacheParam);
} finally {
//清除可能标识
removePossibleNull(cacheParam);
}
}
}
}
}
public final void execute(CacheParam cacheParam, Consumer consumer) {
if (cacheParam == null) {
consumer.accept(null);
return;
}
//查询操作
if (isGet(cacheParam))
throw PRException.of(ServerFailureMsg.fail("非法操作,获取缓存注解方法不存在返回值,缓存key:%s", cacheParam.key));
try {
//执行目标方法
consumer.accept(null);
} catch (Throwable t) {
throw PRException.of(t);
} finally {
after(cacheParam, null);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy