【问题标题】:Can Spring @Cacheable be configured to block on a cache miss?可以将 Spring @Cacheable 配置为阻止缓存未命中吗?
【发布时间】:2012-07-01 00:36:45
【问题描述】:

是否可以配置 Spring @Cacheable,以便如果缓存未命中,对可缓存方法的调用会被阻塞,直到可缓存方法执行一次并填充缓存?

在我的情况下,我正在处理数据库中不经常更改的数据,实际上如果这些数据发生更改,则需要重新启动应用程序。我可以创建@PostConstruct 方法并在每个服务启动时初始化数据,但这似乎不像@Cacheable 注释那样“优雅”。

我打算将 EhCache 与 Spring @Cacheable 注释一起使用。

更新:

以下是我在尝试使用@PostConstruct 时遇到的一些问题,以防其他人遇到这些问题。 @PostConstruct 方法不能是 @Transactional,因为它们在设置对象的属性之后运行,而不是在配置整个 spring 上下文之后运行。因此,您不能假设在调用 @PostConstruct 方法时,TX 管理器已全部设置和配置。解决方法是实现 ApplicationListener 并手动注入 TransactionTemplate ......等等通过使用 @Cacheable 简化了很多额外的工作。

【问题讨论】:

  • 我添加了一个 ApplicationListener 并将其配置为侦听 ContextRefreshedEvent,但是在生命周期中此时执行我的方法仍然为时过早,无法缓存在我的方法上。您能否详细说明您还需要做什么?

标签: spring caching ehcache


【解决方案1】:

在 Spring 4.3 中添加了对同步缓存的支持:

@Service
public class FooService {

    @Cacheable(cacheNames = "foos", sync = true)
    public Foo getFoo(String id) { ... }

}

见:https://spring.io/blog/2016/03/04/core-container-refinements-in-spring-framework-4-3

【讨论】:

    【解决方案2】:

    我不认为@PostConstruct 不优雅,对我来说似乎是完美的解决方案。您希望仅在重新启动应用程序时调用方法。有什么更好的?

    但您也可以这样做来阻止调用,直到缓存可用

    @Cacheable(cacheName="yourCache", decoratedCacheType= DecoratedCacheType.SELF_POPULATING_CACHE)
    public List<String> getWhatever(int id) {
    //call database
    }
    

    并使缓存自动刷新:

    @Cacheable(cacheName="yourCache", refreshInterval=1000, decoratedCacheType= DecoratedCacheType.REFRESHING_SELF_POPULATING_CACHE)
    public List<String> getWhatever(int id) {
      //call database
    }
    

    kudos

    【讨论】:

    • ehcache 和基于并发映射的缓存受支持,但您可以在以下位置拥有一个:static.springsource.org/spring/docs/3.1.0.M1/…
    • 我很确定 @NimChimpsky 使用的是 ehcache-spring-annotations,而不是 Spring 注释(因此链接的文档是错误的)。如果有办法使用纯 Spring 做到这一点,我想听听。我在下面使用ehcache-spring-annotations API 提供了一个更简洁的解决方案。
    【解决方案3】:

    “block on concurrent miss”由(令人讨厌的注解名称相同)@Cacheable from ehcache-spring-annotations 直接支持。只需设置selfPopulating = true

    spring XML 配置也比使用 Spring @Cacheable 干净很多。

    最大的缺点是您将被绑定到 ehcache 并且无法连接其他实现(例如,对单元测试有用)。

    【讨论】:

      猜你喜欢
      • 2016-09-13
      • 2012-04-30
      • 1970-01-01
      • 2021-02-21
      • 2018-02-07
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 2015-07-05
      相关资源
      最近更新 更多