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@Configurationpublic 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; }}
原网址: 访问
创建于: 2023-10-07 16:22:03
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论