Is it possible to set a different specification per cache using caffeine in spring boot?

后端 未结 3 505
Happy的楠姐
Happy的楠姐 2021-02-02 10:03

I have a simple sprint boot application using spring boot 1.5.11.RELEASE with @EnableCaching on the Application Configuration class.

相关标签:
3条回答
  • 2021-02-02 10:19

    This is your only chance:

    @Bean
    public CaffeineCache cacheA() {
        return new CaffeineCache("CACHE_A",
                Caffeine.newBuilder()
                        .expireAfterAccess(1, TimeUnit.DAYS)
                        .build());
    }
    
    @Bean
    public CaffeineCache cacheB() {
        return new CaffeineCache("CACHE_B",
                Caffeine.newBuilder()
                        .expireAfterWrite(7, TimeUnit.DAYS)
                        .recordStats()
                        .build());
    }
    

    Just expose your custom caches as beans. They are automatically added to the CaffeineCacheManager.

    0 讨论(0)
  • 2021-02-02 10:19

    I converted my initial PR into a separate tiny project.

    To start using it just add the latest dependency from Maven Central:

    <dependency>
        <groupId>io.github.stepio.coffee-boots</groupId>
        <artifactId>coffee-boots</artifactId>
        <version>2.0.0</version>
    </dependency>
    

    Format of properties is the following:

    coffee-boots.cache.spec.myCache=maximumSize=100000,expireAfterWrite=1m
    

    If no specific configuration is defined, CacheManager defaults to Spring's behavior.

    0 讨论(0)
  • 2021-02-02 10:31

    I config multiple cache manager like this

        @Bean
        public CacheManager template() {
            CaffeineCacheManager cacheManager = new CaffeineCacheManager(CACHE_TEMPLATE);
            cacheManager.setCaffeine(caffeineCacheBuilder(this.settings.getCacheExpiredInMinutes()));
            return cacheManager;
        }
    
        @Bean
        public CacheManager daily() {
            CaffeineCacheManager cacheManager = new CaffeineCacheManager(CACHE_TEMPLATE);
            cacheManager.setCaffeine(caffeineCacheBuilder(24 * 60));
            return cacheManager;
        }
    

    And use the cache normally

        @Cacheable(cacheManager = "template")
        @Override
        public ArrayList<FmdModel> getData(String arg) {
            return ....;
        }
    

    Update

    It look like the above code has a big mistake. So I change to

    @Configuration
    @Data
    @Slf4j
    @ConfigurationProperties(prefix = "caching")
    public class AppCacheConfig {
    
    
        //This cache spec is load from `application.yml` file
        // @ConfigurationProperties(prefix = "caching")
        private Map<String, CacheSpec> specs;
    
        @Bean
        public CacheManager cacheManager(Ticker ticker) {
            SimpleCacheManager manager = new SimpleCacheManager();
            if (specs != null) {
                List<CaffeineCache> caches = specs.entrySet().stream()
                        .map(entry -> buildCache(entry.getKey(), entry.getValue(), ticker)).collect(Collectors.toList());
                manager.setCaches(caches);
            }
            return manager;
        }
    
        private CaffeineCache buildCache(String name, CacheSpec cacheSpec, Ticker ticker) {
            log.info("Cache {} specified timeout of {} min, max of {}", name, cacheSpec.getTimeout(), cacheSpec.getMax());
            final Caffeine<Object, Object> caffeineBuilder = Caffeine.newBuilder()
                    .expireAfterWrite(cacheSpec.getTimeout(), TimeUnit.MINUTES).maximumSize(cacheSpec.getMax())
                    .ticker(ticker);
            return new CaffeineCache(name, caffeineBuilder.build());
        }
    
        @Bean
        public Ticker ticker() {
            return Ticker.systemTicker();
        }
    }
    
    

    This AppCacheConfig class allow you to define many cache spec as you prefer. And you can define cache spec in application.yml file

    caching:
      specs:
        template:
          timeout: 10 #15 minutes
          max: 10_000
        daily:
          timeout: 1440 #1 day
          max: 10_000
        weekly:
          timeout: 10080 #7 days
          max: 10_000
        ...:
          timeout: ... #in minutes
          max:
    
    

    But still, this class has a limitation that we can only set timeout and max size only. because of CacheSpec class

    @Data
    public class CacheSpec {
    
        private Integer timeout;
        private Integer max = 200;
    
    }
    

    Therefore, If you like to add more config parameters, you are to add more parameters on CacheSpec class and set the Cache configuration on AppCacheConfig.buildCache function.
    Hope this help!

    0 讨论(0)
提交回复
热议问题