在采用数组或集合参数的方法上使用 Spring Cache 有哪些策略?

2024-03-19

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

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

从语义上讲,我需要缓存Entity单独的对象(以 id 为键),而不是基于整个 ID 的集合。类似于什么这个问题 https://stackoverflow.com/questions/13178723/spring-cache-abstraction-with-multi-value-queries正在询问。

简单的 Spring Memcached https://stackoverflow.com/questions/13178723/spring-cache-abstraction-with-multi-value-queries支持我想要的,通过它ReadThroughMultiCache https://stackoverflow.com/questions/13178723/spring-cache-abstraction-with-multi-value-queries,但我想使用 Spring 的抽象来支持轻松更改缓存存储实现(Guava、Coherence、Hazelcast 等),而不仅仅是 memcached。

使用 Spring Cache 缓存此类方法有哪些策略?


Spring的缓存抽象 http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#cache不支持这种开箱即用的行为。然而,这并不意味着不可能;只是需要做更多的工作来支持所需的行为。

我写了一个小example https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CachingCollectionElementsIndividuallyWithConcurrentMapTest.java演示开发人员如何实现这一目标。该示例使用 Spring 的并发映射缓存管理器 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/concurrent/ConcurrentMapCacheManager.html演示定制。此示例需要适应您所需的缓存提供程序(例如 Hazelcast、Coherence 等)。

简而言之,您需要重写缓存管理器 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/CacheManager.html“装饰”的实现方法Cache http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/Cache.html。这因实施而异。在里面ConcurrentMapCacheManager,方法是创建ConcurrentMapCache(名称:字符串) https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java#L136-L143。在 Spring Data GemFire 中,您可以覆盖获取缓存(名称:字符串) https://github.com/spring-projects/spring-data-gemfire/blob/master/src/main/java/org/springframework/data/gemfire/support/GemfireCacheManager.java#L75-L97方法来装饰返回的 Cache。对于番石榴来说,这将是创建GuavaCache(名称:字符串) https://github.com/spring-projects/spring-framework/blob/master/spring-context-support/src/main/java/org/springframework/cache/guava/GuavaCacheManager.java#L190-L197 in the GuavaCacheManager, 等等。

那么你的自定义、修饰的缓存实现 https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CachingCollectionElementsIndividuallyWithConcurrentMapTest.java#L139-L297(也许/理想情况下,委托给实际缓存实现 https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java#L142, from this https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CachingCollectionElementsIndividuallyWithConcurrentMapTest.java#L128)将处理缓存键和相应值的集合。

这种方法有一些局限性:

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

  2. 我的实现只是一个例子,所以我选择不实现Cache.putIfAbsent(键, 值) http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/Cache.html#putIfAbsent-java.lang.Object-java.lang.Object-手术 (here https://github.com/jxblum/spring-gemfire-tests/blob/master/src/test/java/org/spring/cache/CachingCollectionElementsIndividuallyWithConcurrentMapTest.java#L270-L279).

  3. 虽然我的实现有效,但它可以变得更加健壮。

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

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

Cheers!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在采用数组或集合参数的方法上使用 Spring Cache 有哪些策略? 的相关文章

随机推荐