Skip to content

Commit 1dc8201

Browse files
committed
Polish ReactiveAdapterRegisry
1 parent e3e975d commit 1dc8201

File tree

4 files changed

+79
-86
lines changed

4 files changed

+79
-86
lines changed

spring-core/src/main/java/org/springframework/core/ReactiveAdapter.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,11 +24,10 @@
2424
import org.springframework.util.Assert;
2525

2626
/**
27-
* Adapt a Reactive Streams {@link Publisher} to and from an async/reactive type
28-
* such as {@code CompletableFuture}, an RxJava {@code Observable}, etc.
27+
* Adapter for a Reactive Streams {@link Publisher} to and from an async/reactive
28+
* type such as {@code CompletableFuture}, RxJava {@code Observable}, and others.
2929
*
30-
* <p>Use the {@link ReactiveAdapterRegistry} to register reactive types and
31-
* obtain adapters from.
30+
* <p>An adapter is typically obtained via {@link ReactiveAdapterRegistry}.
3231
*
3332
* @author Rossen Stoyanchev
3433
* @since 5.0
@@ -71,37 +70,38 @@ public ReactiveTypeDescriptor getDescriptor() {
7170
}
7271

7372
/**
74-
* A shortcut for {@code getDescriptor().getReactiveType()}.
73+
* Shortcut for {@code getDescriptor().getReactiveType()}.
7574
*/
7675
public Class<?> getReactiveType() {
7776
return getDescriptor().getReactiveType();
7877
}
7978

8079
/**
81-
* A shortcut for {@code getDescriptor().isMultiValue()}.
80+
* Shortcut for {@code getDescriptor().isMultiValue()}.
8281
*/
8382
public boolean isMultiValue() {
8483
return getDescriptor().isMultiValue();
8584
}
8685

8786
/**
88-
* A shortcut for {@code getDescriptor().supportsEmpty()}.
87+
* Shortcut for {@code getDescriptor().supportsEmpty()}.
8988
*/
9089
public boolean supportsEmpty() {
9190
return getDescriptor().supportsEmpty();
9291
}
9392

9493
/**
95-
* A shortcut for {@code getDescriptor().isNoValue()}.
94+
* Shortcut for {@code getDescriptor().isNoValue()}.
9695
*/
9796
public boolean isNoValue() {
9897
return getDescriptor().isNoValue();
9998
}
10099

101100

102101
/**
103-
* Adapt the given instance to a Reactive Streams Publisher.
104-
* @param source the source object to adapt from
102+
* Adapt the given instance to a Reactive Streams {@code Publisher}.
103+
* @param source the source object to adapt from; if the given object is
104+
* {@code null}, {@link ReactiveTypeDescriptor#getEmptyValue()} is used.
105105
* @return the Publisher representing the adaptation
106106
*/
107107
@SuppressWarnings("unchecked")

spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,13 +34,8 @@
3434
import org.springframework.util.ClassUtils;
3535
import org.springframework.util.ReflectionUtils;
3636

37-
import static org.springframework.core.ReactiveTypeDescriptor.multiValue;
38-
import static org.springframework.core.ReactiveTypeDescriptor.noValue;
39-
import static org.springframework.core.ReactiveTypeDescriptor.singleOptionalValue;
40-
import static org.springframework.core.ReactiveTypeDescriptor.singleRequiredValue;
41-
4237
/**
43-
* A registry of adapters to adapt a Reactive Streams {@link Publisher} to/from
38+
* A registry of adapters to adapt Reactive Streams {@link Publisher} to/from
4439
* various async/reactive types such as {@code CompletableFuture}, RxJava
4540
* {@code Observable}, and others.
4641
*
@@ -64,6 +59,7 @@ public class ReactiveAdapterRegistry {
6459

6560
/**
6661
* Create a registry and auto-register default adapters.
62+
* @see #getSharedInstance()
6763
*/
6864
public ReactiveAdapterRegistry() {
6965

@@ -168,49 +164,54 @@ public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Obj
168164
/**
169165
* Return a shared default {@code ReactiveAdapterRegistry} instance, lazily
170166
* building it once needed.
167+
*
171168
* <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured
172169
* {@code ReactiveAdapterRegistry} instance for customization purposes.
173170
* This accessor is only meant as a fallback for code paths that want to
174171
* fall back on a default instance if one isn't provided.
172+
*
175173
* @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null})
176174
* @since 5.0.2
177175
*/
178176
public static ReactiveAdapterRegistry getSharedInstance() {
179-
ReactiveAdapterRegistry ar = sharedInstance;
180-
if (ar == null) {
177+
ReactiveAdapterRegistry registry = sharedInstance;
178+
if (registry == null) {
181179
synchronized (ReactiveAdapterRegistry.class) {
182-
ar = sharedInstance;
183-
if (ar == null) {
184-
ar = new ReactiveAdapterRegistry();
185-
sharedInstance = ar;
180+
registry = sharedInstance;
181+
if (registry == null) {
182+
registry = new ReactiveAdapterRegistry();
183+
sharedInstance = registry;
186184
}
187185
}
188186
}
189-
return ar;
187+
return registry;
190188
}
191189

192190

193191
private static class ReactorRegistrar {
194192

195193
void registerAdapters(ReactiveAdapterRegistry registry) {
196-
// Flux and Mono ahead of Publisher...
194+
195+
// Register Flux and Mono before Publisher...
197196

198197
registry.registerReactiveType(
199-
singleOptionalValue(Mono.class, Mono::empty),
198+
ReactiveTypeDescriptor.singleOptionalValue(Mono.class, Mono::empty),
200199
source -> (Mono<?>) source,
201200
Mono::from
202201
);
203202

204-
registry.registerReactiveType(multiValue(Flux.class, Flux::empty),
203+
registry.registerReactiveType(
204+
ReactiveTypeDescriptor.multiValue(Flux.class, Flux::empty),
205205
source -> (Flux<?>) source,
206206
Flux::from);
207207

208-
registry.registerReactiveType(multiValue(Publisher.class, Flux::empty),
208+
registry.registerReactiveType(
209+
ReactiveTypeDescriptor.multiValue(Publisher.class, Flux::empty),
209210
source -> (Publisher<?>) source,
210211
source -> source);
211212

212213
registry.registerReactiveType(
213-
singleOptionalValue(CompletableFuture.class, () -> {
214+
ReactiveTypeDescriptor.singleOptionalValue(CompletableFuture.class, () -> {
214215
CompletableFuture<?> empty = new CompletableFuture<>();
215216
empty.complete(null);
216217
return empty;
@@ -226,17 +227,17 @@ private static class RxJava1Registrar {
226227

227228
void registerAdapters(ReactiveAdapterRegistry registry) {
228229
registry.registerReactiveType(
229-
multiValue(rx.Observable.class, rx.Observable::empty),
230+
ReactiveTypeDescriptor.multiValue(rx.Observable.class, rx.Observable::empty),
230231
source -> RxReactiveStreams.toPublisher((rx.Observable<?>) source),
231232
RxReactiveStreams::toObservable
232233
);
233234
registry.registerReactiveType(
234-
singleRequiredValue(rx.Single.class),
235+
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class),
235236
source -> RxReactiveStreams.toPublisher((rx.Single<?>) source),
236237
RxReactiveStreams::toSingle
237238
);
238239
registry.registerReactiveType(
239-
noValue(rx.Completable.class, rx.Completable::complete),
240+
ReactiveTypeDescriptor.noValue(rx.Completable.class, rx.Completable::complete),
240241
source -> RxReactiveStreams.toPublisher((rx.Completable) source),
241242
RxReactiveStreams::toCompletable
242243
);
@@ -248,27 +249,27 @@ private static class RxJava2Registrar {
248249

249250
void registerAdapters(ReactiveAdapterRegistry registry) {
250251
registry.registerReactiveType(
251-
multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
252+
ReactiveTypeDescriptor.multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
252253
source -> (io.reactivex.Flowable<?>) source,
253254
Flowable::fromPublisher
254255
);
255256
registry.registerReactiveType(
256-
multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
257+
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
257258
source -> ((io.reactivex.Observable<?>) source).toFlowable(BackpressureStrategy.BUFFER),
258259
source -> io.reactivex.Flowable.fromPublisher(source).toObservable()
259260
);
260261
registry.registerReactiveType(
261-
singleRequiredValue(io.reactivex.Single.class),
262+
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
262263
source -> ((io.reactivex.Single<?>) source).toFlowable(),
263264
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().singleElement().toSingle()
264265
);
265266
registry.registerReactiveType(
266-
singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
267+
ReactiveTypeDescriptor.singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
267268
source -> ((io.reactivex.Maybe<?>) source).toFlowable(),
268269
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().singleElement()
269270
);
270271
registry.registerReactiveType(
271-
noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
272+
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
272273
source -> ((io.reactivex.Completable) source).toFlowable(),
273274
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().ignoreElements()
274275
);
@@ -278,15 +279,15 @@ void registerAdapters(ReactiveAdapterRegistry registry) {
278279

279280
private static class ReactorJdkFlowAdapterRegistrar {
280281

281-
// TODO: remove reflection when build requires JDK 9+
282282
void registerAdapter(ReactiveAdapterRegistry registry) throws Exception {
283+
// TODO: remove reflection when build requires JDK 9+
283284
Class<?> type = ClassUtils.forName("java.util.concurrent.Flow.Publisher", getClass().getClassLoader());
284285
Method toFluxMethod = getMethod("flowPublisherToFlux", type);
285286
Method toFlowMethod = getMethod("publisherToFlowPublisher", Publisher.class);
286287
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
287288

288289
registry.registerReactiveType(
289-
multiValue(type, () -> emptyFlow),
290+
ReactiveTypeDescriptor.multiValue(type, () -> emptyFlow),
290291
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
291292
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher)
292293
);
@@ -299,9 +300,10 @@ private static Method getMethod(String name, Class<?> argumentType) throws NoSuc
299300

300301

301302
/**
302-
* Extension of ReactiveAdapter that wraps adapted (raw) Publisher's as
303-
* {@link Flux} or {@link Mono} depending on the underlying reactive type's
304-
* stream semantics.
303+
* ReactiveAdapter variant that wraps adapted Publishers as {@link Flux} or
304+
* {@link Mono} depending on {@link ReactiveTypeDescriptor#isMultiValue()}.
305+
* This is important in places where only the stream and stream element type
306+
* information is available like encoders and decoders.
305307
*/
306308
private static class ReactorAdapter extends ReactiveAdapter {
307309

spring-core/src/main/java/org/springframework/core/ReactiveTypeDescriptor.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,8 +22,8 @@
2222
import org.springframework.util.Assert;
2323

2424
/**
25-
* Descriptor for a reactive type with information about its stream semantics, i.e.
26-
* how many values it can produce.
25+
* Describes the semantics of a reactive type including boolean checks for
26+
* {@link #isMultiValue()}, {@link #supportsEmpty()}, and {@link #isNoValue()}.
2727
*
2828
* @author Rossen Stoyanchev
2929
* @since 5.0
@@ -55,21 +55,12 @@ private ReactiveTypeDescriptor(Class<?> reactiveType, @Nullable Supplier<?> empt
5555

5656

5757
/**
58-
* Return the reactive type the descriptor was created for.
58+
* Return the reactive type for this descriptor.
5959
*/
6060
public Class<?> getReactiveType() {
6161
return this.reactiveType;
6262
}
6363

64-
/**
65-
* Return an empty-value instance for the underlying reactive or async type.
66-
* Use of this type implies {@link #supportsEmpty()} is true.
67-
*/
68-
public Object getEmptyValue() {
69-
Assert.state(this.emptyValueSupplier != null, "Empty values not supported");
70-
return this.emptyValueSupplier.get();
71-
}
72-
7364
/**
7465
* Return {@code true} if the reactive type can produce more than 1 value
7566
* can be produced and is therefore a good fit to adapt to {@code Flux}.
@@ -95,6 +86,15 @@ public boolean isNoValue() {
9586
return this.noValue;
9687
}
9788

89+
/**
90+
* Return an empty-value instance for the underlying reactive or async type.
91+
* Use of this type implies {@link #supportsEmpty()} is true.
92+
*/
93+
public Object getEmptyValue() {
94+
Assert.state(this.emptyValueSupplier != null, "Empty values not supported");
95+
return this.emptyValueSupplier.get();
96+
}
97+
9898

9999
@Override
100100
public boolean equals(@Nullable Object other) {

0 commit comments

Comments
 (0)