我有以下缓存用例。我正在使用 @Cacheable
注释,它看起来像这样:
@Cacheable(cacheNames = "sampleCache", key = "#customerId", cacheResolver = "sampleCacheResolver")
public @ResponseBody SampleResponse getSampleMethod(String customerId) {
}
TTL 在 sampleCacheResolver
中设置。但是我有一个要求,我必须根据响应对象更改 TTL。例如,在响应对象中,如果说 SampleResponse.month
是当前月份,我想将 ttl 设置为 1 分钟,否则我想保留默认值 3 分钟。
由于 sampleCacheResolver
在请求级别被调用,我不确定如何根据响应更新 ttl。
答案 0 :(得分:0)
开箱即用的 Spring's Cache Abstraction 这是不可能的。
Spring 非常clear,无论是 TTL(生存时间)还是 TTI(空闲超时)过期策略(甚至驱逐策略)都不是由抽象处理的,并且有充分的理由。
Expiration 和 Eviction 实现是特定于缓存提供程序的,当条目过期或被驱逐时,许多实现可能有不同的操作。
将 TTL 应用于响应是相当奇特的,特别是考虑到 TTL 是一个设定的时间范围。
无论如何,您有两个选择。
首先,一些缓存提供程序及其支持的 Spring 位提供与您所寻求的功能接近的功能。
例如,我为 Apache Geode 处理 Spring Boot、Session 和 Data,它们可以在 Spring 的缓存抽象中serve as a caching provider。
我支持的功能之一是通过基于注释的配置模型的入门级(即实体)过期策略。见here。当然,考虑到 Apache Geode 能够表达自定义过期策略,这可以由 Apache Geode 本身实现。也就是说,使用注解实现入门级 TTL 是基于 Apache Geode 的 CustomExpiry
接口。
处理条目/实体或响应 TTL 的另一种方法是覆盖/扩展 Spring 的缓存抽象。抽象中的 2 个主要接口是 CacheManager
和 Cache
接口。
在您的情况下,您将实现 Cache
接口以包含您需要的 TTL 逻辑。您的 Cache
(TTL) 实现将包装实际的缓存提供程序实现(例如 EhCache Cache
)。然后您必须实现 CacheManager
接口来包装缓存提供程序 CacheManager
实现(同样,EhCache CacheManager
)。您的 CacheManager
实现仅用于在框架调用时创建启用 TTL 的 Cache
实现包装提供程序的 Cache
实现的实例。本质上,您启用 TTL 的 Cache
实现正在增强,或decorating 缓存提供程序的 Cache
实现具有您需要的 TTL 逻辑。
另一种可能的解决方案是使用 Spring AOP。实际上,Spring AOP 处理了许多 Spring 的功能,例如缓存或事务管理(分界)。精心设计的 AOP 方面可以包装缓存方面并包含您需要的 TTL 逻辑。您必须确保 TTL AOP Aspect 出现在 Spring 的 Caching Aspect 之后,可以通过 bean 排序来处理。
这次我没有为您的确切用例提供示例。但是,我之前已经回答过需要对 Spring 的 Cache
和 CacheManager
接口进行“自定义”实现的问题。供您参考,您可以参考我的 example 以了解如何实现您自己的 Cache
/CacheManager
组合。
在继续我介绍的路径之前,我鼓励您探索您的缓存提供程序,看看它是否为您提供了您所追求的 TTL 功能。您应该根据自己的需要和要求选择合适的缓存提供程序。
我知道这是很多信息,但我只是想让您有选择并从多个角度思考问题。