Spring ap 中的 Guava 缓存作为基于时间的清理存储

Guava cache as time-based cleanup storage in Spring ap

我有一个 Spring Boot/MVC 应用程序,它应该存储用户发送的一些简单 POJO 15 分钟。当这个时间到期时,这个对象应该从 ConcurrentHashMap 中移除。起初 ConcurrentHashMap 是我想要实现此功能的东西,但后来我认为利用 Guava 的缓存可能是一个更好的选择,因为它具有开箱即用的基于时间的驱逐。

我的服务实现

@CachePut(cacheNames = "teamConfigs", key = "#authAccessDto.accessToken")
@Override
public OAuthAccessDto saveConfig(OAuthAccessDto authAccessDto) {
    return authAccessDto;
}

@Override
@Cacheable(cacheNames = "teamConfigs")
public OAuthAccessDto getConfig(String accessToken) {
    // we assume that the cache is already populated
    return null;
}

如您所见,我们使用 saveConfig 保存数据,然后当我们需要检索它时,我们调用 getConfig

Spring 引导中的缓存配置如下(yml 文件):

spring:
  cache:
    cache-names: teamConfigs
    guava:
      spec: expireAfterWrites=900s

但是,在阅读了Guava的缓存文档后https://github.com/google/guava/wiki/CachesExplained我发现Guava甚至可以在定义的时间之前清理缓存在 expireAfterWrites 过去了( 甚至在此之前 运行 内存不足 )。

我如何配置 Guava Cache 以保留对象直到时间到期(考虑到它没有 运行 内存不足 )。也许我应该选择其他解决方案?

我不知道 Guava,但您可以使用任何符合 JSR-107 的提供程序和一个简单的配置,如下所示:

@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
    return cm -> {
        cm.createCache("teamConfigs", new MutableConfiguration<>()
            .setExpiryPolicyFactory(CreatedExpiryPolicy     
                .factoryOf(new Duration(MINUTES, 15)));
    };
}

Caffeine(用 Java8 重写了 Guava)有一个 JSR-107 提供程序,因此您可以使用它。也许那个版本没有展示您使用 Guava 的体验?如果是这样,预计会在 Spring Boot 1.4 中提供支持,但您现在可以尝试 JSR-107 支持。

如果您不想使用它,可以尝试 expiringmap。它在 Spring 抽象中没有任何 Cache 实现,但由于它是 Map 你可以轻松地包装它,就像在我的头顶上:

@Bean
public Cache teamConfigsCache() {
    Map<Object, Object> map = ExpiringMap.builder()
        .expiration(15, TimeUnit.MINUTES)
        .build();
    return new ConcurrentMapCache("teamConfigs", map , true);
}

如果 Spring Boot 在您的配置中发现至少一个 Cache bean,it auto-creates a CacheManager implementation that wraps them. You can force that behaviour via the spring.cache.type property