Commit 4a9123d6 authored by Stephane Nicoll's avatar Stephane Nicoll

Detect user-defined RedisCacheConfiguration

This commits improves the cache auto-configuration for Redis by looking
up a custom "RedisCacheConfiguration" bean that allows to take full
control over the `RedisCacheManager`.

Closes gh-11599
parent 7d12dc2e
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.cache;
import java.util.LinkedHashSet;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
......@@ -51,16 +52,20 @@ class RedisCacheConfiguration {
private final CacheManagerCustomizers customizerInvoker;
private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration;
RedisCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) {
CacheManagerCustomizers customizerInvoker,
ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable();
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManagerBuilder builder = RedisCacheManager
.builder(redisConnectionFactory).cacheDefaults(getConfiguration());
.builder(redisConnectionFactory).cacheDefaults(determineConfiguration());
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
......@@ -68,7 +73,10 @@ class RedisCacheConfiguration {
return this.customizerInvoker.customize(builder.build());
}
private org.springframework.data.redis.cache.RedisCacheConfiguration getConfiguration() {
private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration() {
if (this.redisCacheConfiguration != null) {
return this.redisCacheConfiguration;
}
Redis redisProperties = this.cacheProperties.getRedis();
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
.defaultCacheConfig();
......
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -279,7 +279,7 @@ public class CacheAutoConfigurationTests {
@Test
public void redisCacheExplicit() {
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class)
this.contextRunner.withUserConfiguration(RedisConfiguration.class)
.withPropertyValues("spring.cache.type=redis",
"spring.cache.redis.time-to-live=15000",
"spring.cache.redis.cacheNullValues=false",
......@@ -300,17 +300,36 @@ public class CacheAutoConfigurationTests {
});
}
@Test
public void redisCacheWithRedisCacheConfiguration() {
this.contextRunner
.withUserConfiguration(RedisWithCacheConfigurationConfiguration.class)
.withPropertyValues("spring.cache.type=redis",
"spring.cache.redis.time-to-live=15000",
"spring.cache.redis.keyPrefix=foo")
.run((context) -> {
RedisCacheManager cacheManager = getCacheManager(context,
RedisCacheManager.class);
assertThat(cacheManager.getCacheNames()).isEmpty();
org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = (org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
cacheManager).getPropertyValue("defaultCacheConfig");
assertThat(redisCacheConfiguration.getTtl())
.isEqualTo(java.time.Duration.ofSeconds(30));
assertThat(redisCacheConfiguration.getKeyPrefix()).contains("bar");
});
}
@Test
public void redisCacheWithCustomizers() {
this.contextRunner
.withUserConfiguration(RedisCacheAndCustomizersConfiguration.class)
.withUserConfiguration(RedisWithCustomizersConfiguration.class)
.withPropertyValues("spring.cache.type=" + "redis")
.run(dunno("allCacheManagerCustomizer", "redisCacheManagerCustomizer"));
}
@Test
public void redisCacheExplicitWithCaches() {
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class)
this.contextRunner.withUserConfiguration(RedisConfiguration.class)
.withPropertyValues("spring.cache.type=redis",
"spring.cache.cacheNames[0]=foo",
"spring.cache.cacheNames[1]=bar")
......@@ -919,7 +938,7 @@ public class CacheAutoConfigurationTests {
@Configuration
@EnableCaching
static class RedisCacheConfiguration {
static class RedisConfiguration {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
......@@ -929,8 +948,22 @@ public class CacheAutoConfigurationTests {
}
@Configuration
@Import({ RedisCacheConfiguration.class, CacheManagerCustomizersConfiguration.class })
static class RedisCacheAndCustomizersConfiguration {
@Import(RedisConfiguration.class)
static class RedisWithCacheConfigurationConfiguration {
@Bean
public org.springframework.data.redis.cache.RedisCacheConfiguration customRedisCacheConfiguration() {
return org.springframework.data.redis.cache.RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(java.time.Duration.ofSeconds(30))
.prefixKeysWith("bar");
}
}
@Configuration
@Import({ RedisConfiguration.class, CacheManagerCustomizersConfiguration.class })
static class RedisWithCustomizersConfiguration {
}
......
......@@ -4638,6 +4638,10 @@ key, Redis does not have overlapping keys and cannot return invalid values. We s
recommend keeping this setting enabled if you create your own `RedisCacheManager`.
====
TIP: You can take full control of the configuration by adding a `RedisCacheConfiguration`
`@Bean` of your own. This can be useful if you're looking for customizing the
serialization strategy.
[[boot-features-caching-provider-caffeine]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment