Merge pull request #22569 from bono007

* pr/22569:
  Polish "Add support for selecting the Redis client to use"
  Add support for selecting the Redis client to use

Closes gh-22569
pull/22740/head
Stephane Nicoll 4 years ago
commit 0bc5b20d56

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 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.
@ -26,6 +26,7 @@ import redis.clients.jedis.JedisPoolConfig;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisClusterConfiguration;
@ -45,6 +46,8 @@ import org.springframework.util.StringUtils;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class }) @ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
@ConditionalOnMissingBean(RedisConnectionFactory.class)
@ConditionalOnProperty(name = "spring.redis.client-type", havingValue = "jedis", matchIfMissing = true)
class JedisConnectionConfiguration extends RedisConnectionConfiguration { class JedisConnectionConfiguration extends RedisConnectionConfiguration {
JedisConnectionConfiguration(RedisProperties properties, JedisConnectionConfiguration(RedisProperties properties,
@ -54,7 +57,6 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration {
} }
@Bean @Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
JedisConnectionFactory redisConnectionFactory( JedisConnectionFactory redisConnectionFactory(
ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException { ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException {
return createJedisConnectionFactory(builderCustomizers); return createJedisConnectionFactory(builderCustomizers);

@ -31,6 +31,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 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.Lettuce.Cluster.Refresh;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool; import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -52,6 +53,7 @@ import org.springframework.util.StringUtils;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisClient.class) @ConditionalOnClass(RedisClient.class)
@ConditionalOnProperty(name = "spring.redis.client-type", havingValue = "lettuce", matchIfMissing = true)
class LettuceConnectionConfiguration extends RedisConnectionConfiguration { class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
LettuceConnectionConfiguration(RedisProperties properties, LettuceConnectionConfiguration(RedisProperties properties,

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 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.
@ -21,6 +21,7 @@ import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -52,6 +53,7 @@ public class RedisAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean(name = "redisTemplate") @ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException { throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); RedisTemplate<Object, Object> template = new RedisTemplate<>();
@ -61,6 +63,7 @@ public class RedisAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException { throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate(); StringRedisTemplate template = new StringRedisTemplate();

@ -76,6 +76,11 @@ public class RedisProperties {
*/ */
private String clientName; private String clientName;
/**
* Type of client to use. By default, auto-detected according to the classpath.
*/
private ClientType clientType;
private Sentinel sentinel; private Sentinel sentinel;
private Cluster cluster; private Cluster cluster;
@ -148,6 +153,14 @@ public class RedisProperties {
this.clientName = clientName; this.clientName = clientName;
} }
public ClientType getClientType() {
return this.clientType;
}
public void setClientType(ClientType clientType) {
this.clientType = clientType;
}
public Sentinel getSentinel() { public Sentinel getSentinel() {
return this.sentinel; return this.sentinel;
} }
@ -172,6 +185,23 @@ public class RedisProperties {
return this.lettuce; return this.lettuce;
} }
/**
* Type of Redis client to use.
*/
public enum ClientType {
/**
* Use the Lettuce redis client.
*/
LETTUCE,
/**
* Use the Jedis redis client.
*/
JEDIS
}
/** /**
* Pool properties. * Pool properties.
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 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.
@ -25,6 +25,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
@ -42,6 +43,18 @@ class RedisAutoConfigurationJedisTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class));
@Test
void connectionFactoryDefaultsToJedis() {
this.contextRunner.run((context) -> assertThat(context.getBean("redisConnectionFactory"))
.isInstanceOf(JedisConnectionFactory.class));
}
@Test
void connectionFactoryIsNotCreatedWhenLettuceIsSelected() {
this.contextRunner.withPropertyValues("spring.redis.client-type=lettuce")
.run((context) -> assertThat(context).doesNotHaveBean(RedisConnectionFactory.class));
}
@Test @Test
void testOverrideRedisConfiguration() { void testOverrideRedisConfiguration() {
this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.database:1").run((context) -> { this.contextRunner.withPropertyValues("spring.redis.host:foo", "spring.redis.database:1").run((context) -> {

@ -37,8 +37,10 @@ import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration; 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;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
@ -72,8 +74,10 @@ class RedisAutoConfigurationTests {
@Test @Test
void testDefaultRedisConfiguration() { void testDefaultRedisConfiguration() {
this.contextRunner.run((context) -> { this.contextRunner.run((context) -> {
assertThat(context.getBean("redisTemplate", RedisOperations.class)).isNotNull(); assertThat(context.getBean("redisTemplate")).isInstanceOf(RedisOperations.class);
assertThat(context.getBean(StringRedisTemplate.class)).isNotNull(); assertThat(context).hasSingleBean(StringRedisTemplate.class);
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context.getBean(RedisConnectionFactory.class)).isInstanceOf(LettuceConnectionFactory.class);
}); });
} }
@ -182,6 +186,22 @@ class RedisAutoConfigurationTests {
}); });
} }
@Test
void connectionFactoryWithJedisClientType() {
this.contextRunner.withPropertyValues("spring.redis.client-type:jedis").run((context) -> {
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context.getBean(RedisConnectionFactory.class)).isInstanceOf(JedisConnectionFactory.class);
});
}
@Test
void connectionFactoryWithLettuceClientType() {
this.contextRunner.withPropertyValues("spring.redis.client-type:lettuce").run((context) -> {
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context.getBean(RedisConnectionFactory.class)).isInstanceOf(LettuceConnectionFactory.class);
});
}
@Test @Test
void testRedisConfigurationWithSentinel() { void testRedisConfigurationWithSentinel() {
List<String> sentinels = Arrays.asList("127.0.0.1:26379", "127.0.0.1:26380"); List<String> sentinels = Arrays.asList("127.0.0.1:26379", "127.0.0.1:26380");

Loading…
Cancel
Save