Skip to content

Commit c40517b

Browse files
committed
Merge pull request #10944 from ryonday:redis-cache-config
* pr/10944: Polish "Improve cache auto-configuration for Redis" Improve cache auto-configuration for Redis Respond to MR feedback Improve spring-boot-autoconfigure for Redis caches
2 parents 25ddd47 + 46ef178 commit c40517b

File tree

5 files changed

+125
-9
lines changed

5 files changed

+125
-9
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*
3030
* @author Stephane Nicoll
3131
* @author Eddú Meléndez
32+
* @author Ryon Day
3233
* @since 1.3.0
3334
*/
3435
@ConfigurationProperties(prefix = "spring.cache")
@@ -55,6 +56,8 @@ public class CacheProperties {
5556

5657
private final JCache jcache = new JCache();
5758

59+
private final Redis redis = new Redis();
60+
5861
public CacheType getType() {
5962
return this.type;
6063
}
@@ -91,6 +94,10 @@ public JCache getJcache() {
9194
return this.jcache;
9295
}
9396

97+
public Redis getRedis() {
98+
return this.redis;
99+
}
100+
94101
/**
95102
* Resolve the config location if set.
96103
* @param config the config resource
@@ -233,4 +240,63 @@ public void setConfig(Resource config) {
233240

234241
}
235242

243+
/**
244+
* Redis-specific cache properties.
245+
*/
246+
public static class Redis {
247+
248+
/**
249+
* Entry expiration in milliseconds. By default the entries never expire.
250+
*/
251+
private long timeToLive = 0;
252+
253+
/**
254+
* Allow caching null values.
255+
*/
256+
private boolean cacheNullValues = true;
257+
258+
/**
259+
* Key prefix.
260+
*/
261+
private String keyPrefix;
262+
263+
/**
264+
* Whether to use the key prefix when writing to Redis.
265+
*/
266+
private boolean useKeyPrefix = true;
267+
268+
public long getTimeToLive() {
269+
return this.timeToLive;
270+
}
271+
272+
public void setTimeToLive(long timeToLive) {
273+
this.timeToLive = timeToLive;
274+
}
275+
276+
public boolean isCacheNullValues() {
277+
return this.cacheNullValues;
278+
}
279+
280+
public void setCacheNullValues(boolean cacheNullValues) {
281+
this.cacheNullValues = cacheNullValues;
282+
}
283+
284+
public String getKeyPrefix() {
285+
return this.keyPrefix;
286+
}
287+
288+
public void setKeyPrefix(String keyPrefix) {
289+
this.keyPrefix = keyPrefix;
290+
}
291+
292+
public boolean isUseKeyPrefix() {
293+
return this.useKeyPrefix;
294+
}
295+
296+
public void setUseKeyPrefix(boolean useKeyPrefix) {
297+
this.useKeyPrefix = useKeyPrefix;
298+
}
299+
300+
}
301+
236302
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/RedisCacheConfiguration.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package org.springframework.boot.autoconfigure.cache;
1818

19+
import java.time.Duration;
1920
import java.util.LinkedHashSet;
2021
import java.util.List;
2122

2223
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
24+
import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis;
2325
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2426
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2527
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
@@ -36,6 +38,7 @@
3638
*
3739
* @author Stephane Nicoll
3840
* @author Mark Paluch
41+
* @author Ryon Day
3942
* @since 1.3.0
4043
*/
4144
@Configuration
@@ -58,12 +61,29 @@ class RedisCacheConfiguration {
5861
@Bean
5962
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
6063
RedisCacheManagerBuilder builder = RedisCacheManager
61-
.builder(redisConnectionFactory);
64+
.builder(redisConnectionFactory).cacheDefaults(getConfiguration());
6265
List<String> cacheNames = this.cacheProperties.getCacheNames();
6366
if (!cacheNames.isEmpty()) {
6467
builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
6568
}
6669
return this.customizerInvoker.customize(builder.build());
6770
}
6871

72+
private org.springframework.data.redis.cache.RedisCacheConfiguration getConfiguration() {
73+
Redis redisProperties = this.cacheProperties.getRedis();
74+
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
75+
.defaultCacheConfig();
76+
config = config.entryTtl(Duration.ofMillis(redisProperties.getTimeToLive()));
77+
if (redisProperties.getKeyPrefix() != null) {
78+
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
79+
}
80+
if (!redisProperties.isCacheNullValues()) {
81+
config = config.disableCachingNullValues();
82+
}
83+
if (!redisProperties.isUseKeyPrefix()) {
84+
config = config.disableKeyPrefix();
85+
}
86+
return config;
87+
}
88+
6989
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
* @author Stephane Nicoll
9191
* @author Eddú Meléndez
9292
* @author Mark Paluch
93+
* @author Ryon Day
9394
*/
9495
@RunWith(ModifiedClassPathRunner.class)
9596
@ClassPathExclusions("hazelcast-client-*.jar")
@@ -280,14 +281,23 @@ public void couchbaseCacheExplicitWithTtl() {
280281
@Test
281282
public void redisCacheExplicit() {
282283
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class)
283-
.withPropertyValues("spring.cache.type=redis").run((context) -> {
284+
.withPropertyValues("spring.cache.type=redis",
285+
"spring.cache.redis.time-to-live=15000",
286+
"spring.cache.redis.cacheNullValues=false",
287+
"spring.cache.redis.keyPrefix=foo",
288+
"spring.cache.redis.useKeyPrefix=false")
289+
.run((context) -> {
284290
RedisCacheManager cacheManager = getCacheManager(context,
285291
RedisCacheManager.class);
286292
assertThat(cacheManager.getCacheNames()).isEmpty();
287-
assertThat(
288-
((org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
289-
cacheManager).getPropertyValue("defaultCacheConfig"))
290-
.usePrefix()).isTrue();
293+
org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = (org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
294+
cacheManager).getPropertyValue("defaultCacheConfig");
295+
assertThat(redisCacheConfiguration.getTtl())
296+
.isEqualTo(java.time.Duration.ofSeconds(15));
297+
assertThat(redisCacheConfiguration.getAllowCacheNullValues())
298+
.isFalse();
299+
assertThat(redisCacheConfiguration.getKeyPrefix()).contains("foo");
300+
assertThat(redisCacheConfiguration.usePrefix()).isFalse();
291301
});
292302
}
293303

@@ -309,6 +319,14 @@ public void redisCacheExplicitWithCaches() {
309319
RedisCacheManager cacheManager = getCacheManager(context,
310320
RedisCacheManager.class);
311321
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
322+
org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = (org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
323+
cacheManager).getPropertyValue("defaultCacheConfig");
324+
assertThat(redisCacheConfiguration.getTtl())
325+
.isEqualTo(java.time.Duration.ofMinutes(0));
326+
assertThat(redisCacheConfiguration.getAllowCacheNullValues())
327+
.isTrue();
328+
assertThat(redisCacheConfiguration.getKeyPrefix()).isEmpty();
329+
assertThat(redisCacheConfiguration.usePrefix()).isTrue();
312330
});
313331
}
314332

spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ content into your application; rather pick only the properties that you need.
7777
spring.cache.infinispan.config= # The location of the configuration file to use to initialize Infinispan.
7878
spring.cache.jcache.config= # The location of the configuration file to use to initialize the cache manager.
7979
spring.cache.jcache.provider= # Fully qualified name of the CachingProvider implementation to use to retrieve the JSR-107 compliant cache manager. Only needed if more than one JSR-107 implementation is available on the classpath.
80+
spring.cache.redis.cache-null-values=true # Allow caching null values.
81+
spring.cache.redis.key-prefix= # Key prefix.
82+
spring.cache.redis.time-to-live=0 # Entry expiration in milliseconds. By default the entries never expire.
83+
spring.cache.redis.use-key-prefix=true # Whether to use the key prefix when writing to Redis.
8084
spring.cache.type= # Cache type, auto-detected according to the environment by default.
8185
8286
# SPRING CONFIG - using environment property only ({sc-spring-boot}/context/config/ConfigFileApplicationListener.{sc-ext}[ConfigFileApplicationListener])

spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4546,9 +4546,17 @@ This sample configuration reuses the `Cluster` that was created via auto-configu
45464546

45474547
[[boot-features-caching-provider-redis]]
45484548
==== Redis
4549-
If Redis is available and configured, the `RedisCacheManager` is auto-configured. It is
4550-
also possible to create additional caches on startup by setting the
4551-
`spring.cache.cache-names` property.
4549+
If Redis is available and configured, a `RedisCacheManager` is auto-configured. It is
4550+
possible to create additional caches on startup by setting the
4551+
`spring.cache.cache-names` property and cache defaults can be configured using
4552+
`spring.redis.cache.*` properties. For instance, the following configuration creates
4553+
`cache1` and `cache2` caches with a _time to live_ of 10 minutes:
4554+
4555+
[source,properties,indent=0]
4556+
----
4557+
spring.cache.cache-names=cache1,cache2
4558+
spring.cache.redis.time-to-live=600000
4559+
----
45524560

45534561
[NOTE]
45544562
====

0 commit comments

Comments
 (0)