OO模块集成 Jetcache 缓存问题
活动Action开发过程中碰到缓存使用的问题,Action中的代码基本从原 service 中迁移,
Jetcache 缓存的注解对Spring 容器内的类生效(现在代码中都作用在@service标记类中),但像Action 这些类手动创建出来实例缓存注解就失效了;
思路1:
- 简单有效的方式,通过显式的 Api 调用来集成,通过抽象类定义存取缓存基础动作,子类显式调用,这种思路下搞到缓存入口CacheManager就行,配合官方demo。
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41public abstract class AbstractActivityHandlerFacility {
protected CacheManager getCacheManager() {
return SpringUtil.getBean(CacheManager.class);
}
private Cache<String, Object> caches;
public AbstractActivityHandlerFacility() {
QuickConfig qc = QuickConfig.newBuilder("userCache")
.expire(Duration.ofSeconds(3600))
.loader(this::loadOrderSumFromDatabase)
.refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS).stopRefreshAfterLastAccess(100, TimeUnit.SECONDS))
.penetrationProtect(true)
.build();
caches = getCacheManager().getOrCreateCache(qc);
}
protected String getCacheKey(String constantPrefix, ActivityContext context) {
return new StringBuilder(constantPrefix)
.append(context.getActivityInstance().getActivityCombineInfo().getActivityBaseInfo().getId())
.append("_")
.append(context.getUserInstance().getUserId()).toString();
}
protected RedisService getRedisService() {
return SpringUtil.getBean(RedisService.class);
}
protected void putToCache(String key, Object value, long timeout, TimeUnit timeUnit) {
caches.put(key, value, timeout, timeUnit);
}
protected <T> T getCache(String key) {
return (T) caches.get(key);
}
protected void clearCache(String key) {
caches.remove(key);
}
}
备注: QuickConfig 是jetcache 2.7.x 版本才有, 项目中v2.6.7
业务代码中手动调用存取数据,代码量多了50%,同时增加了编码的思维负担。
1 |
|
思路1能达到要求,但不够优雅,万不得已情况下实在难以接受。
思路2(目前采用):
不打破现有cache 的编码使用习惯,Action 中可以直接使用@Cached、@CacheInvalidate等注解。
要做到这种程度还是要将Action 调用方 ActivityHandler和容器勾搭上,看看代码找找思路。
过程
spring 容器下注解工作套路,容器生命周期的钩子中触发扫 package->反射->挂切面->动态代理目标对象。
盲猜 jetcache 也差不多,只是时机的选择问题。考古一张spring 的图
源码解读:
- Maven: com.alicp.jetcache:jetcache-anno:2.6.7 注解工作代码
- Maven: com.alicp.jetcache:jetcache-anno-api:2.6.7 注解声明
- Maven: com.alicp.jetcache:jetcache-core:2.6.7 核心实现,没什么和spring相关内容
- Maven: com.alicp.jetcache:jetcache-autoconfigure:2.6.7 springboot 自动装配套路
- Maven: com.alicp.jetcache:jetcache-redis:2.6.7
- Maven: com.alicp.jetcache:jetcache-starter-redis:2.6.7
撸了下代码,跟预想差不多 CreateCacheAnnotationBeanPostProcessor,作为时机 开始初始化缓存注解相关的内容;
层次依次: CacheAdvisor -> CachePointcut ->JetCacheInterceptor
有这三个就具备 aop 条件了。
关键代码:
通过ProxyFactory动态将CacheAdvisor织入activityHandler
1 | public <T> T dynamicCreateActivityHandler(ActivityHandler activityHandler){ |
调用方式和原来service中一样
1 | public class ActionsHandler implements Handler { |
区别是多绕2个弯,原接口doJoinActivity()设计时考虑灵活性,没使用形参而是使用实例成员作为参数,注解中的 key 无法动态计算#userId这种变量
翻了解析逻辑,关键代码ExpressionUtil.eval:61 ,这块看似留了KeyEvaluator作口子用来扩展,但是没有给上下文修Context改的空间,翻了一圈,无计可施。
目前取巧暂时用内部方法包装context,凑合先用,种草 后续来拔。
OO模块集成 Jetcache 缓存问题
https://konbluesky.github.io/2024/12/19/jetcache-integration/