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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.cache; ...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.cache;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis; import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
...@@ -51,16 +52,20 @@ class RedisCacheConfiguration { ...@@ -51,16 +52,20 @@ class RedisCacheConfiguration {
private final CacheManagerCustomizers customizerInvoker; private final CacheManagerCustomizers customizerInvoker;
private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration;
RedisCacheConfiguration(CacheProperties cacheProperties, RedisCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) { CacheManagerCustomizers customizerInvoker,
ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration) {
this.cacheProperties = cacheProperties; this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker; this.customizerInvoker = customizerInvoker;
this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable();
} }
@Bean @Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManagerBuilder builder = RedisCacheManager RedisCacheManagerBuilder builder = RedisCacheManager
.builder(redisConnectionFactory).cacheDefaults(getConfiguration()); .builder(redisConnectionFactory).cacheDefaults(determineConfiguration());
List<String> cacheNames = this.cacheProperties.getCacheNames(); List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) { if (!cacheNames.isEmpty()) {
builder.initialCacheNames(new LinkedHashSet<>(cacheNames)); builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
...@@ -68,7 +73,10 @@ class RedisCacheConfiguration { ...@@ -68,7 +73,10 @@ class RedisCacheConfiguration {
return this.customizerInvoker.customize(builder.build()); 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(); Redis redisProperties = this.cacheProperties.getRedis();
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
.defaultCacheConfig(); .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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -279,7 +279,7 @@ public class CacheAutoConfigurationTests { ...@@ -279,7 +279,7 @@ public class CacheAutoConfigurationTests {
@Test @Test
public void redisCacheExplicit() { public void redisCacheExplicit() {
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class) this.contextRunner.withUserConfiguration(RedisConfiguration.class)
.withPropertyValues("spring.cache.type=redis", .withPropertyValues("spring.cache.type=redis",
"spring.cache.redis.time-to-live=15000", "spring.cache.redis.time-to-live=15000",
"spring.cache.redis.cacheNullValues=false", "spring.cache.redis.cacheNullValues=false",
...@@ -300,17 +300,36 @@ public class CacheAutoConfigurationTests { ...@@ -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 @Test
public void redisCacheWithCustomizers() { public void redisCacheWithCustomizers() {
this.contextRunner this.contextRunner
.withUserConfiguration(RedisCacheAndCustomizersConfiguration.class) .withUserConfiguration(RedisWithCustomizersConfiguration.class)
.withPropertyValues("spring.cache.type=" + "redis") .withPropertyValues("spring.cache.type=" + "redis")
.run(dunno("allCacheManagerCustomizer", "redisCacheManagerCustomizer")); .run(dunno("allCacheManagerCustomizer", "redisCacheManagerCustomizer"));
} }
@Test @Test
public void redisCacheExplicitWithCaches() { public void redisCacheExplicitWithCaches() {
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class) this.contextRunner.withUserConfiguration(RedisConfiguration.class)
.withPropertyValues("spring.cache.type=redis", .withPropertyValues("spring.cache.type=redis",
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[0]=foo",
"spring.cache.cacheNames[1]=bar") "spring.cache.cacheNames[1]=bar")
...@@ -919,7 +938,7 @@ public class CacheAutoConfigurationTests { ...@@ -919,7 +938,7 @@ public class CacheAutoConfigurationTests {
@Configuration @Configuration
@EnableCaching @EnableCaching
static class RedisCacheConfiguration { static class RedisConfiguration {
@Bean @Bean
public RedisConnectionFactory redisConnectionFactory() { public RedisConnectionFactory redisConnectionFactory() {
...@@ -929,8 +948,22 @@ public class CacheAutoConfigurationTests { ...@@ -929,8 +948,22 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@Import({ RedisCacheConfiguration.class, CacheManagerCustomizersConfiguration.class }) @Import(RedisConfiguration.class)
static class RedisCacheAndCustomizersConfiguration { 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 ...@@ -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`. 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]] [[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