diff --git a/pom.xml b/pom.xml
index 507b76dd15..219f179eeb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
* Note that {@link JedisConnection} and its {@link JedisClusterConnection clustered variant} are not Thread-safe and
* instances should not be shared across threads. Refer to the
@@ -103,9 +104,10 @@ public class JedisConnectionFactory
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new PassThroughExceptionTranslationStrategy(
JedisExceptionConverter.INSTANCE);
- private boolean convertPipelineAndTxResults = true;
-
private int phase = 0; // in between min and max values
+ private boolean autoStartup = true;
+ private boolean earlyStartup = true;
+ private boolean convertPipelineAndTxResults = true;
private final AtomicReference
+ * This connection factory defaults to early auto-startup during {@link #afterPropertiesSet()} and can potentially
+ * create Redis connections early on in the lifecycle. See {@link #setEarlyStartup(boolean)} for delaying connection
+ * creation to the ApplicationContext refresh if auto-startup is enabled.
+ *
+ * @param autoStartup {@literal true} to automatically {@link #start()} the connection factory; {@literal false}
+ * otherwise.
+ * @since 3.3
+ * @see #setEarlyStartup(boolean)
+ * @see #start()
+ */
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ /**
+ * @return whether to {@link #start()} the component during {@link #afterPropertiesSet()}.
+ * @since 3.3
+ */
+ public boolean isEarlyStartup() {
+ return this.earlyStartup;
+ }
+
+ /**
+ * Configure if this InitializingBean's component Lifecycle should get started early by {@link #afterPropertiesSet()}
+ * at the time that the bean is initialized. The component defaults to auto-startup.
+ *
+ * This method is related to {@link #setAutoStartup(boolean) auto-startup} and can be used to delay Redis client
+ * startup until the ApplicationContext refresh. Disabling early startup does not disable auto-startup.
+ *
+ * @param earlyStartup {@literal true} to early {@link #start()} the component; {@literal false} otherwise.
+ * @since 3.3
+ * @see #setAutoStartup(boolean)
+ */
+ public void setEarlyStartup(boolean earlyStartup) {
+ this.earlyStartup = earlyStartup;
+ }
+
/**
* Specifies if pipelined results should be converted to the expected data type. If {@code false}, results of
* {@link JedisConnection#closePipeline()} and {@link JedisConnection#exec()} will be of the type returned by the
@@ -616,7 +682,7 @@ public void afterPropertiesSet() {
this.clientConfig = createClientConfig(getDatabase(), getRedisUsername(), getRedisPassword());
- if (isAutoStartup()) {
+ if (isEarlyStartup()) {
start();
}
}
@@ -724,21 +790,6 @@ public void stop() {
}
}
- @Override
- public int getPhase() {
- return this.phase;
- }
-
- /**
- * Specify the lifecycle phase for pausing and resuming this executor. The default is {@code 0}.
- *
- * @since 3.2
- * @see SmartLifecycle#getPhase()
- */
- public void setPhase(int phase) {
- this.phase = phase;
- }
-
@Override
public boolean isRunning() {
return State.STARTED.equals(this.state.get());
diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java
index 2b6ac76503..c406faaa1e 100644
--- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java
+++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java
@@ -100,8 +100,9 @@
* This connection factory implements {@link InitializingBean} and {@link SmartLifecycle} for flexible lifecycle
* control. It must be {@link #afterPropertiesSet() initialized} and {@link #start() started} before you can obtain a
* connection. {@link #afterPropertiesSet() Initialization} {@link SmartLifecycle#start() starts} this bean
- * {@link #isAutoStartup() by default}. You can {@link SmartLifecycle#stop()} and {@link SmartLifecycle#start() restart}
- * this connection factory if needed.
+ * {@link #isEarlyStartup() early} by default. You can {@link SmartLifecycle#stop()} and {@link SmartLifecycle#start()
+ * restart} this connection factory if needed. Disabling {@link #isEarlyStartup() early startup} leaves lifecycle
+ * management to the container refresh if {@link #isAutoStartup() auto-startup} is enabled.
*
* @author Costin Leau
* @author Jennifer Hickey
@@ -121,13 +122,14 @@ public class LettuceConnectionFactory implements RedisConnectionFactory, Reactiv
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new PassThroughExceptionTranslationStrategy(
LettuceExceptionConverter.INSTANCE);
+ private int phase = 0; // in between min and max values
+ private boolean autoStartup = true;
+ private boolean earlyStartup = true;
private boolean convertPipelineAndTxResults = true;
private boolean eagerInitialization = false;
+
private boolean shareNativeConnection = true;
private boolean validateConnection = false;
-
- private int phase = 0; // in between min and max values
-
private @Nullable AbstractRedisClient client;
private final AtomicReference
+ * This connection factory defaults to early auto-startup during {@link #afterPropertiesSet()} and can potentially
+ * create Redis connections early on in the lifecycle. See {@link #setEarlyStartup(boolean)} for delaying connection
+ * creation to the ApplicationContext refresh if auto-startup is enabled.
+ *
+ * @param autoStartup {@literal true} to automatically {@link #start()} the connection factory; {@literal false}
+ * otherwise.
+ * @since 3.3
+ * @see #setEarlyStartup(boolean)
+ * @see #start()
+ */
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ /**
+ * @return whether to {@link #start()} the component during {@link #afterPropertiesSet()}.
+ * @since 3.3
+ */
+ public boolean isEarlyStartup() {
+ return this.earlyStartup;
+ }
+
+ /**
+ * Configure if this InitializingBean's component Lifecycle should get started early by {@link #afterPropertiesSet()}
+ * at the time that the bean is initialized. The component defaults to auto-startup.
+ *
+ * This method is related to {@link #setAutoStartup(boolean) auto-startup} and can be used to delay Redis client
+ * startup until the ApplicationContext refresh. Disabling early startup does not disable auto-startup.
+ *
+ * @param earlyStartup {@literal true} to early {@link #start()} the component; {@literal false} otherwise.
+ * @since 3.3
+ * @see #setAutoStartup(boolean)
+ */
+ public void setEarlyStartup(boolean earlyStartup) {
+ this.earlyStartup = earlyStartup;
+ }
+
/**
* Specifies if pipelined results should be converted to the expected data type. If {@code false}, results of
* {@link LettuceConnection#closePipeline()} and {LettuceConnection#exec()} will be of the type returned by the
@@ -924,21 +991,6 @@ public void stop() {
state.set(State.STOPPED);
}
- @Override
- public int getPhase() {
- return this.phase;
- }
-
- /**
- * Specify the lifecycle phase for pausing and resuming this executor. The default is {@code 0}.
- *
- * @since 3.2
- * @see SmartLifecycle#getPhase()
- */
- public void setPhase(int phase) {
- this.phase = phase;
- }
-
@Override
public boolean isRunning() {
return State.STARTED.equals(this.state.get());
@@ -947,7 +999,7 @@ public boolean isRunning() {
@Override
public void afterPropertiesSet() {
- if (isAutoStartup()) {
+ if (isEarlyStartup()) {
start();
}
}
diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
index 950a09aacc..f6e3f3f9e4 100644
--- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
@@ -35,6 +35,7 @@
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.jupiter.api.Test;
+
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
@@ -337,6 +338,21 @@ void afterPropertiesTriggersConnectionInitialization() {
assertThat(connectionFactory.isRunning()).isTrue();
}
+ @Test // GH-2866
+ void earlyStartupDoesNotStartConnectionFactory() {
+
+ JedisConnectionFactory connectionFactory = new JedisConnectionFactory(new JedisPoolConfig());
+
+ connectionFactory.setEarlyStartup(false);
+ connectionFactory.afterPropertiesSet();
+
+ assertThat(connectionFactory.isEarlyStartup()).isFalse();
+ assertThat(connectionFactory.isAutoStartup()).isTrue();
+ assertThat(connectionFactory.isRunning()).isFalse();
+
+ assertThat(ReflectionTestUtils.getField(connectionFactory, "pool")).isNull();
+ }
+
private JedisConnectionFactory initSpyedConnectionFactory(RedisSentinelConfiguration sentinelConfiguration,
@Nullable JedisPoolConfig poolConfig) {
diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java
index 2c29c12e52..b4dd713fbe 100644
--- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactoryUnitTests.java
@@ -1260,6 +1260,22 @@ void createRedisConfigurationWithValidRedisUriString() {
.extracting(RedisStandaloneConfiguration::getPort).isEqualTo(6789);
}
+ @Test // GH-2866
+ void earlyStartupDoesNotStartConnectionFactory() {
+
+ LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(new RedisStandaloneConfiguration(),
+ LettuceTestClientConfiguration.defaultConfiguration());
+ connectionFactory.setEarlyStartup(false);
+ connectionFactory.afterPropertiesSet();
+
+ assertThat(connectionFactory.isEarlyStartup()).isFalse();
+ assertThat(connectionFactory.isAutoStartup()).isTrue();
+ assertThat(connectionFactory.isRunning()).isFalse();
+
+ AbstractRedisClient client = (AbstractRedisClient) getField(connectionFactory, "client");
+ assertThat(client).isNull();
+ }
+
static class CustomRedisConfiguration implements RedisConfiguration, WithHostAndPort {
private String hostName;