Skip to content

Commit c0bef2c

Browse files
committed
Lazily start resources on demand (if necessary outside of lifecycle)
See gh-32945
1 parent c3a0eaa commit c0bef2c

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

spring-web/src/main/java/org/springframework/http/client/ReactorResourceFactory.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ public class ReactorResourceFactory
6161
private Supplier<ConnectionProvider> connectionProviderSupplier = () -> ConnectionProvider.create("webflux", 500);
6262

6363
@Nullable
64-
private ConnectionProvider connectionProvider;
64+
private volatile ConnectionProvider connectionProvider;
6565

6666
private Supplier<LoopResources> loopResourcesSupplier = () -> LoopResources.create("webflux-http");
6767

6868
@Nullable
69-
private LoopResources loopResources;
69+
private volatile LoopResources loopResources;
7070

7171
private boolean manageConnectionProvider = false;
7272

@@ -141,16 +141,22 @@ public void setConnectionProvider(ConnectionProvider connectionProvider) {
141141

142142
/**
143143
* Return the configured {@link ConnectionProvider}.
144+
* <p>Lazily tries to start the resources on demand if not initialized yet.
145+
* @see #start()
144146
*/
145147
public ConnectionProvider getConnectionProvider() {
146-
Assert.state(this.connectionProvider != null, "ConnectionProvider not initialized yet");
147-
return this.connectionProvider;
148+
if (this.connectionProvider == null) {
149+
start();
150+
}
151+
ConnectionProvider connectionProvider = this.connectionProvider;
152+
Assert.state(connectionProvider != null, "ConnectionProvider not initialized");
153+
return connectionProvider;
148154
}
149155

150156
/**
151157
* Use this when you don't want to participate in global resources and
152158
* you want to customize the creation of the managed {@code LoopResources}.
153-
* <p>By default, {@code LoopResources.create("reactor-http")} is used.
159+
* <p>By default, {@code LoopResources.create("webflux-http")} is used.
154160
* <p>Note that this option is ignored if {@code userGlobalResources=false} or
155161
* {@link #setLoopResources(LoopResources)} is set.
156162
* @param supplier the supplier to use
@@ -170,10 +176,16 @@ public void setLoopResources(LoopResources loopResources) {
170176

171177
/**
172178
* Return the configured {@link LoopResources}.
179+
* <p>Lazily tries to start the resources on demand if not initialized yet.
180+
* @see #start()
173181
*/
174182
public LoopResources getLoopResources() {
175-
Assert.state(this.loopResources != null, "LoopResources not initialized yet");
176-
return this.loopResources;
183+
if (this.loopResources == null) {
184+
start();
185+
}
186+
LoopResources loopResources = this.loopResources;
187+
Assert.state(loopResources != null, "LoopResources not initialized");
188+
return loopResources;
177189
}
178190

179191
/**
@@ -220,13 +232,25 @@ public void setApplicationContext(ApplicationContext applicationContext) {
220232
}
221233

222234

235+
/**
236+
* Starts the resources if initialized outside an ApplicationContext.
237+
* This is for backwards compatibility; the preferred way is to rely on
238+
* the ApplicationContext's {@link SmartLifecycle lifecycle management}.
239+
* @see #start()
240+
*/
223241
@Override
224242
public void afterPropertiesSet() {
225243
if (this.applicationContext == null) {
226244
start();
227245
}
228246
}
229247

248+
/**
249+
* Stops the resources if initialized outside an ApplicationContext.
250+
* This is for backwards compatibility; the preferred way is to rely on
251+
* the ApplicationContext's {@link SmartLifecycle lifecycle management}.
252+
* @see #stop()
253+
*/
230254
@Override
231255
public void destroy() {
232256
if (this.applicationContext == null) {

spring-web/src/test/java/org/springframework/http/client/ReactorResourceFactoryTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,22 @@ protected void finishRefresh() {
261261
assertThat(resourceFactory.isRunning()).isFalse();
262262
}
263263

264+
@Test
265+
void lazilyStartOnConnectionProviderAccess() {
266+
assertThat(this.resourceFactory.isRunning()).isFalse();
267+
this.resourceFactory.getConnectionProvider();
268+
assertThat(this.resourceFactory.isRunning()).isTrue();
269+
this.resourceFactory.stop();
270+
assertThat(this.resourceFactory.isRunning()).isFalse();
271+
}
272+
273+
@Test
274+
void lazilyStartOnLoopResourcesAccess() {
275+
assertThat(this.resourceFactory.isRunning()).isFalse();
276+
this.resourceFactory.getLoopResources();
277+
assertThat(this.resourceFactory.isRunning()).isTrue();
278+
this.resourceFactory.stop();
279+
assertThat(this.resourceFactory.isRunning()).isFalse();
280+
}
281+
264282
}

0 commit comments

Comments
 (0)