【问题标题】:What strategies exist for using Spring Cache on methods that take an array or collection parameter?在采用数组或集合参数的方法上使用 Spring Cache 存在哪些策略?
【发布时间】:2016-02-12 23:26:41
【问题描述】:

我想使用 Spring 的 Cache 抽象来将方法注释为 @Cacheable。但是,有些方法被设计为采用一个数组或参数集合并返回一个集合。例如,考虑这种方法来查找实体:

public Collection<Entity> getEntities(Collection<Long> ids)

在语义上,我需要单独缓存 Entity 对象(由 id 键入),而不是基于整个 ID 的集合。类似于this question 所询问的内容。

Simple Spring Memcached 支持我想要的,通过它的ReadThroughMultiCache,但我想使用 Spring 的抽象来支持缓存存储实现(Guava、Coherence、Hazelcast 等)的轻松更改,而不仅仅是 memcached。

使用 Spring Cache 缓存这种方法有哪些策略?

【问题讨论】:

    标签: spring caching spring-cache


    【解决方案1】:

    Spring's Cache Abstraction 不支持这种开箱即用的行为。但是,这并不意味着不可能;只需要多做一点工作来支持所需的行为。

    我写了一个小的example 来演示开发人员如何实现这一点。该示例使用 Spring 的 ConcurrentMapCacheManager 来演示自定义。此示例需要适应您所需的缓存提供程序(例如 Hazelcast、Coherence 等)。

    简而言之,您需要重写 CacheManager 实现的方法来“装饰”Cache。这因实施而异。在ConcurrentMapCacheManager中,方法是createConcurrentMapCache(name:String)。在 Spring Data GemFire 中,您将覆盖 getCache(name:String) 方法来装饰返回的缓存。对于 Guava,它将是 GuavaCacheManager 中的 createGuavaCache(name:String),依此类推。

    然后您的custom, decorated Cache implementation(也许/理想情况下,委托给实际的Cache impl,来自this)将处理键和对应值的缓存集合。

    这种方法有一些限制:

    1. 缓存未命中是全有或全无;即,如果缺少任何单个键,则缓存的部分键将被视为未命中。 Spring (OOTB) 不允许您同时返回缓存值并调用 diff 的方法。这需要对缓存抽象进行一些非常广泛的修改,我不建议这样做。

    2. 我的实现只是一个示例,所以我选择不实现 Cache.putIfAbsent(key, value) 操作 (here)。

    3. 虽然我的实现工作正常,但它可以变得更加健壮。

    无论如何,我希望它能提供一些关于如何正确处理这种情况的见解。

    测试类是自包含的(使用 Spring JavaConfig)并且可以在没有任何额外依赖项的情况下运行(除了 Spring、JUnit 和 JRE)。

    干杯!

    【讨论】:

    • 我还应该指出,如果您提前知道您不打算切换缓存提供程序,那么您可以在提供程序方面实现Cache 操作。例如,如果 Memcached 使用 ReadThroughMultiCache 来处理这个问题,那么您可以根据 ReadThroughMultiCache 来实现 Cache.get(key) 操作(可能还有 put?)。但是,根据您的描述,我的解决方案试图(大部分)与缓存提供程序无关。
    • 约翰,我很欣赏你的努力和想法,但限制 #1 对我来说是一个交易破坏者。我们需要智能地缓存,这样键列表中的项目就不会是“全有或全无”。只要列表中存在缓存项,我们就需要使用它们。
    • 好吧,不幸的是,在我的脑海中,除了将自己(在一定程度上)绑定在底层缓存提供程序上之外,我想不出更好的方法来让这更智能。无论如何,该框架非常灵活,因为它为您提供了扩展选项,以自定义行为。但是,开箱即用,这将很难支持,尤其是在缓存提供程序之间保持一致。对此类问题的建议或其他想法持开放态度。
    • @JohnBlum 非常有用
    【解决方案2】:

    为我工作。这是我的答案的链接。 https://stackoverflow.com/a/60992530/2891027

    TL:DR

    @Cacheable(cacheNames = "test", key = "#p0")
    public List<String> getTestFunction(List<String> someIds) {
    

    我的示例是使用 String,但它也适用于 Integer 和 Long,可能还有其他。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 2019-05-29
      • 1970-01-01
      • 2016-09-08
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多