public interface ILocalCache<K, V>{
/**
* 从缓存中获取数据
* @param key
* @return value
*/
public V get(K key);
}
/**
* @Description: 用于初始化cache的参数及其缺省值
*/
public abstract class AbstractLoadingCache<K,V> {
private static final Logger logger= LoggerFactory.getLogger(AbstractLoadingCache.class);
/**
* 最大缓存条数。子类在构造方法中调用setMaximumSize(int size)来更改
*/
protected int maximumSize = 10000;
/**
* 当缓存项在指定的时间段内没有被读或写就会被回收。子类在构造方法中调用setExpireAfterAccessDuration(int duration)来更改
*/
protected int expireAfterAccessDuration = 60;
/**
* 当缓存项在指定的时间段内没有更新就会被回收。子类在构造方法中调用setExpireAfterWriteDuration(int duration)来更改
*/
protected int expireAfterWriteDuration = 30;
/**
* 数据存在时长,子类在构造方法中调用setRefreshAfterWriteDuration(int duration)来更改
*/
protected int refreshAfterWriteDuration = 10;
/**
* 时间单位(分钟)
*/
protected TimeUnit timeUnit = TimeUnit.MINUTES;
/**
* Cache初始化或被重置的时间
*/
protected Date resetTime;
/**
* 历史最高记录数
*/
protected long highestSize = 0;
/**
* 历史最高记录时间
*/
protected Date highestTime;
/**
* 初始化方法
*/
protected abstract void init();
/**
* 获取当前类实例
* @return cache
*/
protected abstract com.google.common.cache.LoadingCache<K, V> getCache();
/**
* 根据key从数据库或其他数据源中获取一个value,并被自动保存到缓存中。
* @param key
* @return value,连同key一起被加载到缓存中的。
*/
protected abstract V fetchData(K key);
/**
* 从缓存中获取数据(第一次自动调用fetchData从外部获取数据),并处理异常
* @param key
* @return Value
* @throws ExecutionException
*/
protected V getValue(K key) throws ExecutionException {
LoadingCache<K, V> cache = getCache();
V result = cache.get(key);
long cacheSize = cache.size();
if (cacheSize > highestSize) {
highestSize = cacheSize;
highestTime = new Date();
logger.debug(getSimpleClassName()+":本地缓存{"+key+"}初始化成功!");
}
return result;
}
/**
* 获取当前类的名字(含类全路径)
* @return
*/
protected String getClassName() {
return this.getClass().getName();
}
/**
* 获取当前类的名字(不含类全路径)
* @return
*/
protected String getSimpleClassName() {
return this.getClass().getSimpleName();
}
/**
* 获取当前缓存器历史最高缓存对象数量
* @return long
*/
public long getHighestSize() {
return highestSize;
}
/**
* 获取当前缓存器历史最高记录时间
* @return
*/
public Date getHighestTime() {
return highestTime;
}
/**
* 设置缓存初始化或者重置时间
* @param resetTime
*/
public void setResetTime(Date resetTime) {
this.resetTime = resetTime;
}
public Date getResetTime() {
return resetTime;
}
/**
* 设置最大缓存条数
* @param maximumSize
*/
public void setMaximumSize(int maximumSize) {
this.maximumSize = maximumSize;
}
public int getMaximumSize() {
return maximumSize;
}
/**
* 设置数据没有被访问时,存在时长
* @param expireAfterAccessDuration
*/
public void setExpireAfterAccessDuration(int expireAfterAccessDuration) {
this.expireAfterAccessDuration = expireAfterAccessDuration;
}
public int getExpireAfterAccessDuration() {
return expireAfterAccessDuration;
}
/**
* 设置数据没有被更新时,存在时长
* @param expireAfterWriteDuration
*/
public void setExpireAfterWriteDuration(int expireAfterWriteDuration) {
this.expireAfterWriteDuration = expireAfterWriteDuration;
}
public int getExpireAfterWriteDuration() {
return expireAfterWriteDuration;
}
/**
* 设置数据刷新时长
* @param refreshAfterWriteDuration
*/
public void setRefreshAfterWriteDuration(int refreshAfterWriteDuration) {
this.refreshAfterWriteDuration = refreshAfterWriteDuration;
}
public int getRefreshAfterWriteDuration() {
return refreshAfterWriteDuration;
}
}
public abstract class CommonCache<T, V> extends AbstractLoadingCache<String, Map<String, V>> implements ILocalCache<String,
Map<String, V>> {
private final Logger logger = LoggerFactory.getLogger(CommonCache.class);
/**
* 缓存容器的初始容量
*/
private final static int initialCapacity = 512;
/**
* 并发级别,并发级别是指可以同时写缓存的线程数
*/
private final static int concurrencyLevel = 4;
/**
* 自动加载缓存
*/
public volatile LoadingCache<String, Map<String, V>> loadingCache;
/**
* guava线程池,用来产生ListenableFuture
*/
private static ListeningExecutorService service = MoreExecutors.listeningDecorator(new ThreadPoolExecutor(2, 4, 10, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(2)));
public CommonCache() {
}
public CommonCache(int expreTime) {
// 最大缓存条数
setMaximumSize(1024);
// 数据刷新时长
setRefreshAfterWriteDuration(expreTime);
this.init();
}
/**
* 初始化
*/
@Override
protected void init() {
// 方式一
loadingCache = CacheBuilder.newBuilder().maximumSize(maximumSize)
// 设置缓存容器的初始容量
.initialCapacity(initialCapacity)
// 设置并发级别,并发级别是指可以同时写缓存的线程数
.concurrencyLevel(concurrencyLevel)
// 每refreshAfterWriteDuration.timeUnit刷新数据
.refreshAfterWrite(refreshAfterWriteDuration, timeUnit)
.build(new CacheLoader<String, Map<String, V>>() {
@Override
public Map<String, V> load(String key) throws Exception {
Map<String, V> value = fetchData(key);
logger.debug(getSimpleClassName() + ":本地缓存{" + key + "}设置成功!");
return value;
}
@Override
public ListenableFuture<Map<String, V>> reload(final String key, final Map<String, V> oldValue) {
logger.debug(Thread.currentThread().getName() + "......后台线程池异步reload刷新:" + key);
ListenableFuture<Map<String, V>> listenableFuture = service.submit(new Callable<Map<String, V>>() {
@Override
public Map<String, V> call() {
Map<String, V> value = fetchData(key);
logger.debug(Thread.currentThread().getName() + " success to mock query db...");
logger.debug(getSimpleClassName() + "后台线程池异步reload刷新:本地缓存{" + key + "}设置成功!");
return value;
}
});
Futures.addCallback(listenableFuture, new FutureCallback<Map<String, V>>() {
@Override
public void onSuccess(Map<String, V> result) {
logger.error("CommonCache刷新缓存成功");
}
@Override
public void onFailure(Throwable e) {
logger.error("CommonCache刷新缓存异常", e);
}
});
return listenableFuture;
}
});
// 方式二
loadingCache = CacheBuilder.newBuilder()
.maximumSize(10)
.refreshAfterWrite(7, TimeUnit.SECONDS)
.build(CacheLoader.asyncReloading(new CacheLoader<String, Map<String, V>>() {
@Override
public Map<String, V> load(String key) throws Exception {
logger.info("用户周期库存缓存超时时间-自动刷新:{}", key);
Map<String, V> value = fetchData(key);
return value;
}
}, Executors.newSingleThreadExecutor()));
this.resetTime = new Date();
this.highestTime = new Date();
}
/**
* 重写获取实例方法获取当前类实例
* @return cache
*/
@Override
public LoadingCache<String, Map<String, V>> getCache() {
// 使用双重校验锁保证只有一个cache实例
if (loadingCache == null) {
synchronized (this) {
if (loadingCache == null) {
this.init();
}
}
}
return loadingCache;
}
@Override
public Map<String, V> get(String key) {
try {
Map<String, V> returnVal = getValue(key);
return returnVal;
} catch (ExecutionException e) {
logger.error(getSimpleClassName() + ":执行异常-无法根据key={" + key + "}获取value,可能是数据库中无该记录。", e);
return null;
} catch (Exception e) {
logger.error(getSimpleClassName() + ":无法根据key={" + key + "}获取value,可能是数据库中无该记录。", e);
return null;
}
}
}
public class CodeMapMasCache extends CommonCache<CodeMapMapper,CodeMapMasDTO> {
private static final Logger logger = LoggerFactory.getLogger(CodeMapMasCache.class);
private CodeMapMapper codeMapMapper;
public CodeMapMasCache(CodeMapMapper codeMapMapper,int expreTime) {
super(expreTime);
this.codeMapMapper=codeMapMapper;
loadingCache.put(BusinessConstant.CacheName.CodeMapMasCache, fetchData(null));
}
@Override
protected Map<String,CodeMapMasDTO> fetchData(String key) {
logger.debug(getSimpleClassName()+":本地缓存{"+"key"+"},正在从数据库中获取CodeMapMasDTO!获取时间:"+new Date());
List<CodeMapMasDTO> codeMapInfoList = null;
Map<String, CodeMapMasDTO> resultMap = new HashMap<String, CodeMapMasDTO>();
try {
codeMapInfoList = codeMapMapper.getAllCodeMapMasCache();
for (CodeMapMasDTO codeMapMasDTO : codeMapInfoList) {
resultMap.put(codeMapMasDTO.getCodeId(), codeMapMasDTO);
}
} catch (Exception e) {
logger.error(getSimpleClassName() + ":===codeMapMapper.getAllCodeMapMasCache()===查询基础参数信息失败:", e);
}
return resultMap;
}
}
@RefreshScope
@Configuration
public class CacheConfig {
@Value("${codemap.cache.expires.time:10}")
private int cacheExpiresTimeCodeMapMasCache;
@Autowired(required = false)
private CodeMapMapper codeMapMapper;
@ConditionalOnExpression("${enable.codemap.cache:true}")
@ConditionalOnBean(name = "codeMapMapper")
@Bean
public CodeMapMasCache codeMapMasCache(){
return new CodeMapMasCache(codeMapMapper,cacheExpiresTimeCodeMapMasCache);
}
}
@Component("guavaCacheService")
public class GuavaCacheServiceImpl implements GuavaCacheService {
@Autowired(required = false)
private CodeMapMasCache codeMapMasCache;
@Autowired(required = false)
private CodeMapMapper codeMapMapper;
public Map<String, CodeMapMasDTO> getCodeMapMasCache() {
Map<String, CodeMapMasDTO> codeMap = null;
codeMap = codeMapMasCache.get(BusinessConstant.CacheName.CodeMapMasCache);
return codeMap;
}
@Override
public CodeMapMasDTO getCodeMapMasCacheSingle(String codeId) {
CodeMapMasDTO codeMapMasDTO = null;
Map<String, CodeMapMasDTO> map = this.getCodeMapMasCache();
if (!CollectionUtils.isEmpty(map)) {
codeMapMasDTO = map.get(codeId);
}
return codeMapMasDTO;
}
@Override
public String getCodeMapMasCacheAttr1(String codeId) {
CodeMapMasDTO codeMapMasDTO = this.getCodeMapMasCacheSingle(codeId);
if (codeMapMasDTO != null) {
return codeMapMasDTO.getAttribute1();
}
return null;
}
@Override
public String getCodeMapMasCacheAttr2(String codeId) {
CodeMapMasDTO codeMapMasDTO = this.getCodeMapMasCacheSingle(codeId);
if (codeMapMasDTO != null) {
return codeMapMasDTO.getAttribute2();
}
return null;
}
@Override
public String getCodeMapMasCacheAttr3(String codeId) {
CodeMapMasDTO codeMapMasDTO = this.getCodeMapMasCacheSingle(codeId);
if (codeMapMasDTO != null) {
return codeMapMasDTO.getAttribute3();
}
return null;
}
@Override
public String getCodeMapMasCacheAttr4(String codeId) {
CodeMapMasDTO codeMapMasDTO = this.getCodeMapMasCacheSingle(codeId);
if (codeMapMasDTO != null) {
return codeMapMasDTO.getAttribute4();
}
return null;
}
}