Guava Cache自动加载异步刷新代码实现-CSDN博客

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
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论