我们使用 Spring Cache 抽象和 Infinispan 服务器作为慢速服务面前的远程缓存。
我有两个要求:
你能建议我如何实现这个吗?
内置
@Cacheable
注释不支持此功能。
我应该使用带有方面的自定义注释吗?对于方面中的第二个要求,我可以处理与远程 Infinispan 服务器的连接问题。
介绍了这个简单的
CustomCacheable
注释
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomCacheable {
// cache name
String value() default "";
}
通过以下方面,我成功地满足了这两个要求:
@Component
@Aspect
public class CustomCacheableAspect {
private static final Logger logger = LoggerFactory.getLogger(CustomCacheableAspect.class);
private CacheManager cacheManager;
public CustomCacheableAspect(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Pointcut("@annotation(com.example.infinispandemo.custom.CustomCacheable)")
public void customCacheablePointcut() {
}
@Around("customCacheablePointcut()")
public Object allMethodCallsWithCustomCacheableAnnotationAdvice(ProceedingJoinPoint jp) throws Throwable {
CustomCacheable a = findCustomCacheableAnnotation(jp);
String cacheName = a.value();
Object key = getKey(jp);
RemoteCache<Object, Object> remoteCache;
try {
remoteCache = getOrCreateCache(cacheManager, cacheName);
} catch (TransportException e) {
logger.warn("Cache `{}` connection error `{}`", cacheName, e.getMessage());
return jp.proceed();
}
Object cacheValue = remoteCache.get(key);
if (cacheValue == null) {
logger.warn("Cache `{}` miss for key `{}`", cacheName, key);
Object result = jp.proceed();
remoteCache.put(key, result);
return result;
} else {
return cacheValue;
}
}
private RemoteCache<Object, Object> getOrCreateCache(CacheManager cacheManager, String cacheName) {
return ((SpringRemoteCacheManager) cacheManager).getNativeCacheManager()
.administration().getOrCreateCache(cacheName, "default");
}
private CustomCacheable findCustomCacheableAnnotation(ProceedingJoinPoint jp) {
return AnnotationUtils.findAnnotation(((MethodSignature) jp.getSignature()).getMethod(), CustomCacheable.class);
}
private Object getKey(ProceedingJoinPoint jp) {
return jp.getArgs()[0];
}
}