本文共 4984 字,大约阅读时间需要 16 分钟。
@Cached(name = "contractOrPdInfo",timeUnit = TimeUnit.HOURS,expire = 24) @CacheRefresh(refresh = 1,timeUnit = TimeUnit.HOURS) public ContractDetailVO findDetailByPdBaseIdAndContractBaseIdAndVersion(Integer pdBaseId, Integer contractBaseId, Double version) { code.....}
比如我使用注解创建了方法缓存,我方法返回的vo是 几张表的数据组合而成的,这几张表的数据有改动的话,这个方法的缓存也会过期.JetCache 提供了CacheRefresh 注解,我们可以设置缓存自动刷新时间,到了时间,他会解析出每个缓存key对应的方法参数,然后调用你这个方法,把得到的结果更新到缓存的value中.但是实时性不高.不满足我的需求.
于是我就想办法如何主动通知jetcache,去清除这个方法的所有缓存,因为方法参数并不包含我那几张表的全部id,所以只能吧缓存全部清除,让他下一次读取不到缓存.
要解决这个问题要有以下几个步骤:
1 给表定义别名 我称之为 namespace 比如t_user的namespace是 user
2 添加自定义注解,获取一个方法的缓存数据依赖哪几张表. 注解名字为:AutoClearCache
/** * fhs framework 对于 jetcahce的扩展注解 * 用于namespaces 的数据改变之后 自动清除缓存 * by wanglei */@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.FIELD,ElementType.TYPE,})public @interface AutoClearCache { /** * 需要自动清除缓存的命名空间 * @return */ String[] namespaces() default {};}
3 搞一个管理器,允许业务根据namespace 去清除此namespace相关的 方法缓存.
管理器大概这么几个部分:
A 项目启动后,根据注解找到所有的需要CacheUpdateManager 管理的所有的方法,缓存起来,建立好和namespace的关系
B 当有业务要调用clearcache的时候,根据namespace找到 相关的方法对象.
然后根据方法对象找到缓存对象(不同版本的jetcache 实现方法不同,我用的2.5.16)
根据方法对象找到所有的刷新缓存的task,根据task可以找到缓存的key
然后调用缓存的.remove方法吧对应的key干掉.
** * 缓存刷新管理器 * 在项目启动完成后获取所有的@AutoRefresCache 标记的方法 */@Datapublic class CacheUpdateManager implements ApplicationContextAware, ApplicationListener{ /** * service的包路径 */ private String[] packageNames = new String[]{}; @Autowired private ConfigMap cacheConfigMap; private ApplicationContext applicationContext; private GlobalCacheConfig globalCacheConfig; /** * key namespace value value namespace 对应的刷新器 */ private Map > methodPontMap = new HashMap<>(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 清除某个namespace的所有缓存 * * @param namespace */ public void clearCache(String namespace) { List methodPoints = methodPontMap.get(namespace); if (methodPoints == null || methodPoints.isEmpty()) { return; } for (MethodPoint methodPoint : methodPoints) { clearAndRefreshMethodCache(methodPoint); } } /** * 清除并且自动刷新方法缓存 * * @param point 方法 */ public void clearAndRefreshMethodCache(MethodPoint point) { if (globalCacheConfig == null) { globalCacheConfig = applicationContext.getBean(GlobalCacheConfig.class); } if (globalCacheConfig == null || !globalCacheConfig.isEnableMethodCache()) { return; } String key = CachePointcut.getKey(point.getMethod(), point.getClazz()); CacheInvokeConfig cac = cacheConfigMap.getByMethodInfo(key); if (cac == null || cac == CacheInvokeConfig.getNoCacheInvokeConfigInstance()) { return; } CacheInvokeContext context = globalCacheConfig.getCacheContext().createCacheInvokeContext(cacheConfigMap); context.setCacheInvokeConfig(cac); context.setHiddenPackages(globalCacheConfig.getHiddenPackages()); CacheInvokeConfig cic = context.getCacheInvokeConfig(); CachedAnnoConfig cachedAnnoConfig = cic.getCachedAnnoConfig(); Cache cache = context.getCacheFunction().apply(context, cachedAnnoConfig); if(cache == null){ return; } if (cache instanceof RefreshCache) { ConcurrentHashMap
全部源码地址:
开源项目地址:
fhs framework qq群:976278956
转载地址:http://yhwni.baihongyu.com/