1515 */
1616package org .springframework .http .client .reactive ;
1717
18+ import java .util .function .Consumer ;
19+ import java .util .function .Supplier ;
20+
1821import reactor .netty .http .HttpResources ;
1922import reactor .netty .resources .ConnectionProvider ;
2023import reactor .netty .resources .LoopResources ;
3740 */
3841public class ReactorResourceFactory implements InitializingBean , DisposableBean {
3942
40- private boolean globalResources = true ;
43+ private boolean useGlobalResources = true ;
44+
45+ @ Nullable
46+ private Consumer <HttpResources > globalResourcesConsumer ;
47+
48+
49+ private Supplier <ConnectionProvider > connectionProviderSupplier = () -> ConnectionProvider .elastic ("http" );
50+
51+ private Supplier <LoopResources > loopResourcesSupplier = () -> LoopResources .create ("reactor-http" );
52+
4153
4254 @ Nullable
4355 private ConnectionProvider connectionProvider ;
4456
4557 @ Nullable
4658 private LoopResources loopResources ;
4759
48- private String threadPrefix = "reactor-http" ;
60+
61+ private boolean manageConnectionProvider = false ;
62+
63+ private boolean manageLoopResources = false ;
4964
5065
5166 /**
52- * Whether to expose and manage the global Reactor Netty resources from the
53- * {@link HttpResources} holder.
54- * <p>Default is "true" in which case this factory helps to configure and
55- * shut down the global Reactor Netty resources within the lifecycle of a
56- * Spring {@code ApplicationContext}.
57- * <p>If set to "false" then the factory creates and manages its own
58- * {@link LoopResources} and {@link ConnectionProvider}, independent of the
59- * global ones in the {@link HttpResources} holder.
60- * @param globalResources whether to expose and manage the global resources
67+ * Whether to use global Reactor Netty resources via {@link HttpResources}.
68+ * <p>Default is "true" in which case this factory initializes and stops the
69+ * global Reactor Netty resources within Spring's {@code ApplicationContext}
70+ * lifecycle. If set to "false" the factory manages its resources independent
71+ * of the global ones.
72+ * @param useGlobalResources whether to expose and manage the global resources
73+ * @see #addGlobalResourcesConsumer(Consumer)
6174 */
62- public void setGlobalResources (boolean globalResources ) {
63- this .globalResources = globalResources ;
75+ public void setUseGlobalResources (boolean useGlobalResources ) {
76+ this .useGlobalResources = useGlobalResources ;
6477 }
6578
6679 /**
67- * Configure the {@link ConnectionProvider} to use.
68- * <p>By default, initialized with {@link ConnectionProvider#elastic(String)}.
69- * @param connectionProvider the connection provider to use
80+ * Add a Consumer for configuring the global Reactor Netty resources on
81+ * startup. When this option is used, {@link #setUseGlobalResources} is also
82+ * enabled.
83+ * @param consumer the consumer to apply
84+ * @see #setUseGlobalResources(boolean)
7085 */
71- public void setConnectionProvider (@ Nullable ConnectionProvider connectionProvider ) {
72- this .connectionProvider = connectionProvider ;
86+ public void addGlobalResourcesConsumer (Consumer <HttpResources > consumer ) {
87+ this .useGlobalResources = true ;
88+ this .globalResourcesConsumer = this .globalResourcesConsumer != null ?
89+ this .globalResourcesConsumer .andThen (consumer ) : consumer ;
7390 }
7491
7592 /**
76- * Configure the {@link LoopResources} to use.
77- * <p>By default, initialized with {@link LoopResources#create(String)}.
78- * @param loopResources the loop resources to use
93+ * Use this option when you don't want to participate in global resources and
94+ * you want to customize the creation of the managed {@code ConnectionProvider}.
95+ * <p>By default, {@code ConnectionProvider.elastic("http")} is used.
96+ * <p>Note that this option is ignored if {@code userGlobalResources=false} or
97+ * {@link #setConnectionProvider(ConnectionProvider)} is set.
98+ * @param supplier the supplier to use
7999 */
80- public void setLoopResources (@ Nullable LoopResources loopResources ) {
81- this .loopResources = loopResources ;
100+ public void setConnectionProviderSupplier (@ Nullable Supplier <ConnectionProvider > supplier ) {
101+ this .connectionProviderSupplier = supplier ;
102+ }
103+
104+ /**
105+ * Use this option when you don't want to participate in global resources and
106+ * you want to customize the creation of the managed {@code LoopResources}.
107+ * <p>By default, {@code LoopResources.create("reactor-http")} is used.
108+ * <p>Note that this option is ignored if {@code userGlobalResources=false} or
109+ * {@link #setLoopResources(LoopResources)} is set.
110+ * @param supplier the supplier to use
111+ */
112+ public void setLoopResourcesSupplier (@ Nullable Supplier <LoopResources > supplier ) {
113+ this .loopResourcesSupplier = supplier ;
114+ }
115+
116+ /**
117+ * Use this option when you want to provide an externally managed
118+ * {@link ConnectionProvider} instance.
119+ * @param connectionProvider the connection provider to use as is
120+ */
121+ public void setConnectionProvider (@ Nullable ConnectionProvider connectionProvider ) {
122+ this .connectionProvider = connectionProvider ;
82123 }
83124
84125 /**
85- * Configure the thread prefix to initialize {@link LoopResources} with. This
86- * is used only when a {@link LoopResources} instance isn't
87- * {@link #setLoopResources(LoopResources) provided}.
88- * <p>By default set to "reactor-http".
89- * @param threadPrefix the thread prefix to use
126+ * Use this option when you want to provide an externally managed
127+ * {@link LoopResources} instance.
128+ * @param loopResources the loop resources to use as is
90129 */
91- public void setThreadPrefix (String threadPrefix ) {
92- Assert .notNull (threadPrefix , "Thread prefix is required" );
93- this .threadPrefix = threadPrefix ;
130+ public void setLoopResources (@ Nullable LoopResources loopResources ) {
131+ this .loopResources = loopResources ;
94132 }
95133
96134
97135 /**
98136 * Whether this factory exposes the global
99137 * {@link reactor.netty.http.HttpResources HttpResources} holder.
100138 */
101- public boolean isGlobalResources () {
102- return this .globalResources ;
139+ public boolean isUseGlobalResources () {
140+ return this .useGlobalResources ;
103141 }
104142
105143 /**
106144 * Return the configured {@link ConnectionProvider}.
107145 */
108- @ Nullable
109146 public ConnectionProvider getConnectionProvider () {
147+ Assert .notNull (this .connectionProvider , "ConnectionProvider not initialized yet via InitializingBean." );
110148 return this .connectionProvider ;
111149 }
112150
113151 /**
114152 * Return the configured {@link LoopResources}.
115153 */
116- @ Nullable
117154 public LoopResources getLoopResources () {
155+ Assert .notNull (this .loopResources , "LoopResources not initialized yet via InitializingBean." );
118156 return this .loopResources ;
119157 }
120158
121- /**
122- * Return the configured prefix for event loop threads.
123- */
124- public String getThreadPrefix () {
125- return this .threadPrefix ;
126- }
127-
128159
129160 @ Override
130161 public void afterPropertiesSet () throws Exception {
131- if (this .loopResources == null ) {
132- this .loopResources = LoopResources .create (this .threadPrefix );
133- }
134- if (this .connectionProvider == null ) {
135- this .connectionProvider = ConnectionProvider .elastic ("http" );
162+ if (this .useGlobalResources ) {
163+ Assert .isTrue (this .loopResources == null && this .connectionProvider == null ,
164+ "'useGlobalResources' is mutually exclusive with explicitly configured resources." );
165+ HttpResources httpResources = HttpResources .get ();
166+ if (this .globalResourcesConsumer != null ) {
167+ this .globalResourcesConsumer .accept (httpResources );
168+ }
136169 }
137- if (this .globalResources ) {
138- HttpResources .set (this .loopResources );
139- HttpResources .set (this .connectionProvider );
170+ else {
171+ if (this .loopResources == null ) {
172+ this .manageLoopResources = true ;
173+ this .loopResources = this .loopResourcesSupplier .get ();
174+ }
175+ if (this .connectionProvider == null ) {
176+ this .manageConnectionProvider = true ;
177+ this .connectionProvider = this .connectionProviderSupplier .get ();
178+ }
140179 }
141180 }
142181
143182 @ Override
144183 public void destroy () {
145- if (this .globalResources ) {
184+ if (this .useGlobalResources ) {
146185 HttpResources .disposeLoopsAndConnections ();
147186 }
148187 else {
149188 try {
150189 ConnectionProvider provider = this .connectionProvider ;
151- if (provider != null ) {
190+ if (provider != null && this . manageConnectionProvider ) {
152191 provider .dispose ();
153192 }
154193 }
@@ -158,7 +197,7 @@ public void destroy() {
158197
159198 try {
160199 LoopResources resources = this .loopResources ;
161- if (resources != null ) {
200+ if (resources != null && this . manageLoopResources ) {
162201 resources .dispose ();
163202 }
164203 }
0 commit comments