将多个咖啡因加载缓存添加到Spring CaffeineCacheManager

8hhllhi2  于 2023-01-24  发布在  Spring
关注(0)|答案(3)|浏览(215)

我想在Spring CacheManager中添加几个不同的LoadingCache,但是我不知道如何使用CaffeineCacheManager来实现这一点。看起来只有一个加载器可以用来刷新内容,但是我需要为每个缓存添加单独的加载器。是否可以在Spring缓存管理器中添加多个加载缓存?如果可以,那么怎么做?

CaffeineCacheManager cacheManage = new CaffeineCacheManager();

LoadingCache<String, Optional<Edition>> loadingCache1 = 
            Caffeine.newBuilder()
            .maximumSize(150)
            .refreshAfterWrite(5, TimeUnit.MINUTES)
            .build(test -> this.testRepo.find(test));

LoadingCache<String, Optional<Edition>> loadingCache2 = 
            Caffeine.newBuilder()
            .maximumSize(150)
            .refreshAfterWrite(5, TimeUnit.MINUTES)
            .build(test2 -> this.testRepo.find2(test2));

// How do I add to cache manager, and specify a name?
neskvpey

neskvpey1#

是的,这是可能的。因为你需要微调每个缓存,你可能更擅长于自己定义它们。回到你的例子,下一步是:

SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
    new CaffeineCache("first", loadingCache1),
    new CaffeineCache("second", loadingCache2)));

然后你可以像往常一样使用它,例如。

@Cacheable("first")
public Foo load(String id) { ... }

如果您使用的是Sping Boot ,您可以将单个缓存公开为bean(因此org.springframework.cache.Cache实现),我们将检测它们并自动为您创建一个SimpleCacheManager
请注意,此策略允许您在不同的实现中使用该高速缓存抽象。first可以是咖啡因缓存,second可以是来自另一个提供程序的缓存。

ymzxtsji

ymzxtsji2#

拥有这个类将允许您在需要的地方正常使用@Cacheable("cacheA")

@EnableCaching
@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager manager = new CaffeineCacheManager();
        manager.registerCustomCache("cacheA", defaultCache());
        manager.registerCustomCache("cacheB", bigCache());
        manager.registerCustomCache("cacheC", longCache());
        // to avoid dynamic caches and be sure each name is assigned to a specific config (dynamic = false)
        // throws error when tries to use a new cache
        manager.setCacheNames(Collections.emptyList());
        return manager;
    }

    private static Cache<Object, Object> defaultCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build();
    }

    private static Cache<Object, Object> bigCache() {
        return Caffeine.newBuilder()
                .maximumSize(5000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build();
    }

    private static Cache<Object, Object> longCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(1, TimeUnit.HOURS)
                .build();
    }
}
vmpqdwk3

vmpqdwk33#

感谢@rado,这是他回答的改进版本。这样我们就可以直接从应用程序属性配置该高速缓存

cache:
  specs:
    big-cache:
      expire-after: WRITE
      timeout: 2h
      max-size: 1000
    long-cache:
      expire-after: ACCESS
      timeout: 30d
      max-size: 100

我们需要为此设置缓存属性

@Data
@EnableConfigurationProperties
@Configuration
@ConfigurationProperties(prefix = "cache")
public class CacheProperties {

    private static final int DEFAULT_CACHE_SIZE = 100;

    private Map<String, CacheSpec> specs = new HashMap<>();

    @Data
    public static class  CacheSpec {
        private Duration timeout;
        private Integer maxSize = DEFAULT_CACHE_SIZE;
        private ExpireAfter expireAfter = ExpireAfter.WRITE;
    }

    enum ExpireAfter { WRITE, ACCESS }
}

然后我们可以直接从外部配置文件进行配置

@EnableCaching
@Configuration
@RequiredArgsConstructor
public class CacheConfiguration {

    private final CacheProperties cacheProperties;

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager manager = new CaffeineCacheManager();

        Map<String, CacheProperties.CacheSpec> specs = cacheProperties.getSpecs();
        specs.keySet().forEach(cacheName -> {
            CacheProperties.CacheSpec spec = specs.get(cacheName);
            manager.registerCustomCache(cacheName, buildCache(spec));
        });

        // to avoid dynamic caches and be sure each name is assigned
        // throws error when tries to use a new cache
        manager.setCacheNames(Collections.emptyList());
        return manager;
    }

    private Cache<Object, Object> buildCache(CacheProperties.CacheSpec cacheSpec) {
        if (cacheSpec.getExpireAfter() == CacheProperties.ExpireAfter.ACCESS) {
            return Caffeine.newBuilder()
                    .expireAfterAccess(cacheSpec.getTimeout())
                    .build();
        }
        return Caffeine.newBuilder()
                .expireAfterWrite(cacheSpec.getTimeout())
                .build();
    }
}

现在,您可以通过使用缓存名称来使用该高速缓存

@Cacheable(cacheNames = "big-cache", key = "{#key}", unless="#result == null")
    public Object findByKeyFromBigCache(String key) {
        // create the required object and return
    }

    @Cacheable(cacheNames = "long-cache", key = "{#key}", unless="#result == null")
    public Object findByKeyFromLongCache(String key) {
        // create the required object and return
    }

相关问题