From ac651442fa82817a13654208328c3e45188fa305 Mon Sep 17 00:00:00 2001 From: bono007 Date: Tue, 4 Aug 2020 23:51:24 -0500 Subject: [PATCH] Add support for selecting the Redis client to use See gh-22569 --- .../redis/JedisConnectionConfiguration.java | 5 +++- .../redis/LettuceConnectionConfiguration.java | 3 ++ .../data/redis/RedisProperties.java | 29 +++++++++++++++++++ .../RedisAutoConfigurationJedisTests.java | 6 ++++ .../redis/RedisAutoConfigurationTests.java | 21 +++++++++++++- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java index ff47497500..dd16409c62 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java @@ -26,6 +26,7 @@ import redis.clients.jedis.JedisPoolConfig; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; @@ -42,9 +43,12 @@ import org.springframework.util.StringUtils; * * @author Mark Paluch * @author Stephane Nicoll + * @author Chris Bono */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class }) +@ConditionalOnMissingBean(RedisConnectionFactory.class) +@ConditionalOnProperty(name = "spring.redis.client-type", havingValue = "jedis", matchIfMissing = true) class JedisConnectionConfiguration extends RedisConnectionConfiguration { JedisConnectionConfiguration(RedisProperties properties, @@ -54,7 +58,6 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration { } @Bean - @ConditionalOnMissingBean(RedisConnectionFactory.class) JedisConnectionFactory redisConnectionFactory( ObjectProvider builderCustomizers) throws UnknownHostException { return createJedisConnectionFactory(builderCustomizers); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java index dca260f473..1084b8b312 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java @@ -31,6 +31,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Lettuce.Cluster.Refresh; import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool; import org.springframework.context.annotation.Bean; @@ -49,9 +50,11 @@ import org.springframework.util.StringUtils; * * @author Mark Paluch * @author Andy Wilkinson + * @author Chris Bono */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(RedisClient.class) +@ConditionalOnProperty(name = "spring.redis.client-type", havingValue = "lettuce", matchIfMissing = true) class LettuceConnectionConfiguration extends RedisConnectionConfiguration { LettuceConnectionConfiguration(RedisProperties properties, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java index c762541a1d..c1c87ed211 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisProperties.java @@ -76,6 +76,11 @@ public class RedisProperties { */ private String clientName; + /** + * Type of client to use. + */ + private ClientType clientType = ClientType.Lettuce; + private Sentinel sentinel; private Cluster cluster; @@ -148,6 +153,14 @@ public class RedisProperties { this.clientName = clientName; } + public ClientType getClientType() { + return this.clientType; + } + + public void setClientType(ClientType clientType) { + this.clientType = clientType; + } + public Sentinel getSentinel() { return this.sentinel; } @@ -172,6 +185,22 @@ public class RedisProperties { return this.lettuce; } + /** + * Type of Redis client to use. + */ + public enum ClientType { + + /** + * Use the Lettuce client + */ + Lettuce, + + /** + * Use the Jedis client + */ + Jedis + } + /** * Pool properties. */ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationJedisTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationJedisTests.java index 9bc153a49f..0aa6c515d2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationJedisTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationJedisTests.java @@ -42,6 +42,12 @@ class RedisAutoConfigurationJedisTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)); + @Test + void testDefaultRedisConfiguration() { + this.contextRunner.run((context) -> assertThat(context.getBean("redisConnectionFactory")) + .isInstanceOf(JedisConnectionFactory.class)); + } + @Test void testOverrideRedisConfiguration() { this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.database:1").run((context) -> { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java index 5a1424d21d..4b50cbcd9e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java @@ -39,6 +39,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisSentinelConfiguration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; @@ -52,7 +53,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** - * Tests for {@link RedisAutoConfiguration}. + * Tests for {@link RedisAutoConfiguration} when both Jedis and Lettuce are on the + * classpath. * * @author Dave Syer * @author Christian Dupuis @@ -74,6 +76,8 @@ class RedisAutoConfigurationTests { this.contextRunner.run((context) -> { assertThat(context.getBean("redisTemplate", RedisOperations.class)).isNotNull(); assertThat(context.getBean(StringRedisTemplate.class)).isNotNull(); + assertThat(context.getBean("redisConnectionFactory")).isInstanceOf(LettuceConnectionFactory.class); + assertThat(context.getBeanProvider(JedisConnectionConfiguration.class).getIfAvailable()).isNull(); }); } @@ -182,6 +186,21 @@ class RedisAutoConfigurationTests { }); } + @Test + void testRedisConfigurationWithClientNameJedis() { + this.contextRunner.withPropertyValues("spring.redis.client-type:jedis") + .run((context) -> assertThat(context.getBean("redisConnectionFactory")) + .isInstanceOf(JedisConnectionFactory.class)); + } + + @Test + void testRedisConfigurationWithClientNameLettuce() { + this.contextRunner.withPropertyValues("spring.redis.client-type:lettuce").run((context) -> { + assertThat(context.getBean("redisConnectionFactory")).isInstanceOf(LettuceConnectionFactory.class); + assertThat(context.getBeanProvider(JedisConnectionConfiguration.class).getIfAvailable()).isNull(); + }); + } + @Test void testRedisConfigurationWithSentinel() { List sentinels = Arrays.asList("127.0.0.1:26379", "127.0.0.1:26380");