I have a simple sprint boot application using spring boot 1.5.11.RELEASE
with @EnableCaching
on the Application Configuration
class.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
spring.cache.type=caffeine
spring.cache.cache-names=cache-a,cache-b
spring.cache.caffeine.spec=maximumSize=100, expireAfterWrite=1d
My question is simple, how can one specify a different size/expiration per cache. E.g. perhaps it's acceptable for cache-a
to be valid for 1 day
. But cache-b
might be ok for 1 week
. The specification on a caffeine cache appears to be global to the CacheManager
rather than Cache
. Am I missing something? Perhaps there is a more suitable provider for my use case?
Caffeine Cache Configuration The Caffeine spec define the cache maximum size as 500 and a time to live of 10 minutes.
Similar to Ehcache, Caffeine cannot work as a distributed cache.
The primary way to use caching in Spring Boot is with the @Cacheable annotation. This annotation works on any method of a Spring bean (or even the entire class). It instructs the registered cache manager to store the result of the method call in a cache.
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
.
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 ....; }
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!
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.
Instead of using SimpleCacheManager, you can use registerCustomCache() method of CaffeineCacheManager. Below is an example:
CaffeineCacheManager manager = new CaffeineCacheManager();
manager.registerCustomCache("Cache1",Caffeine.newBuilder().maximumSize(1000).expireAfterAccess(6, TimeUnit.MINUTES).build());
manager.registerCustomCache("Cache2",Caffeine.newBuilder().maximumSize(2000).expireAfterAccess(12, TimeUnit.MINUTES).build());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With