The automatic configuration of a cache is amazing for the simple cases, however quickly becomes weird if you decide to use multiple CacheManager instances.
For example you might want to have a Distributed Cache using Redis, and a Local Caffeine or ConcurrentMap Cache for small items, you'd need the following configuration.
@Configuration
@EnableCaching
public CachingConfig implements CachingConfigurer, ApplicationContextAware {
private ApplicationContext ac;
@Bean
public CacheManager redisCacheManager(RedisConnectionFactory factory, CacheProperties props) {
// Implementing Redis Cache
}
@Bean
public CacheManager caffeineCache(CacheProperties cacheProperties) {
// Implementing Caffeine Cache
}
@Override
@Bean
public CacheResolver cacheResolver() {
var redisCache = ac.getBean("redisCacheManager", CacheManager.class);
var caffeineCache = ac.getBean("caffeineCache", CacheManager.class);
// Implement Resolver
}
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ac= applicationContext;
}
}
From a user perspective there are some parts that are a little verbose compared to other configurations. Highlights would be bringing in the ApplicationContext, but the class really doesn't care for it, implementing the KeyGenerator using the same default Spring does (per CachingConfigurer Docs), and then not overriding CachingConfigurer::cacheManager() for a mixture of reasons.
I personally I think Caching could use a more "Default unless Declared" approach, where we could reduce this down to the following.
@Configuration
@EnableCaching
public CachingConfig {
@Bean
public CacheManager redisCacheManager(RedisConnectionFactory factory, CacheProperties props) {
// Implementing Redis Cache
}
@Bean
public CacheManager caffeineCache(CacheProperties cacheProperties) {
// Implementing Caffeine Cache
}
@Bean
public CacheResolver cacheResolver(
@Qualifier("redisCacheManager") CacheManager redis,
@Qualifier("caffeineCache") CacheManager caffeine
) {
// Implement Resolver
}
}
This removes the KeyGenerator, swaps ApplicationContext::getBean with Parameter Injection, and removes the CachingConfigurer in favor of global bean detection. What other adjustments would the Spring Boot Team be open to?
The automatic configuration of a cache is amazing for the simple cases, however quickly becomes weird if you decide to use multiple
CacheManagerinstances.For example you might want to have a Distributed Cache using Redis, and a Local Caffeine or ConcurrentMap Cache for small items, you'd need the following configuration.
From a user perspective there are some parts that are a little verbose compared to other configurations. Highlights would be bringing in the
ApplicationContext, but the class really doesn't care for it, implementing theKeyGeneratorusing the same default Spring does (per CachingConfigurer Docs), and then not overridingCachingConfigurer::cacheManager()for a mixture of reasons.I personally I think Caching could use a more "Default unless Declared" approach, where we could reduce this down to the following.
This removes the
KeyGenerator, swapsApplicationContext::getBeanwith Parameter Injection, and removes theCachingConfigurerin favor of global bean detection. What other adjustments would the Spring Boot Team be open to?