Skip to content

Commit bdd9a55

Browse files
committed
Streamline ReactiveAdapterRegistry.getAdapter usage
Closes gh-22842
1 parent 42fda0b commit bdd9a55

File tree

3 files changed

+44
-41
lines changed

3 files changed

+44
-41
lines changed

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

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -118,13 +118,10 @@ else if (Collection.class.isAssignableFrom(parameter.getParameterType())) {
118118
}
119119
else {
120120
valueClass = parameter.getParameterType();
121-
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
122-
if (reactiveAdapterRegistry.hasAdapters()) {
123-
ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass);
124-
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
125-
reactiveSuffix = ClassUtils.getShortName(valueClass);
126-
valueClass = parameter.nested().getNestedParameterType();
127-
}
121+
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(valueClass);
122+
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
123+
reactiveSuffix = ClassUtils.getShortName(valueClass);
124+
valueClass = parameter.nested().getNestedParameterType();
128125
}
129126
}
130127

@@ -207,13 +204,10 @@ else if (Collection.class.isAssignableFrom(resolvedType)) {
207204
}
208205
else {
209206
valueClass = resolvedType;
210-
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
211-
if (reactiveAdapterRegistry.hasAdapters()) {
212-
ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass);
213-
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
214-
reactiveSuffix = ClassUtils.getShortName(valueClass);
215-
valueClass = ResolvableType.forMethodReturnType(method).getGeneric().toClass();
216-
}
207+
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(valueClass);
208+
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
209+
reactiveSuffix = ClassUtils.getShortName(valueClass);
210+
valueClass = ResolvableType.forMethodReturnType(method).getGeneric().toClass();
217211
}
218212
}
219213

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

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -41,7 +41,7 @@
4141
*
4242
* <p>By default, depending on classpath availability, adapters are registered
4343
* for Reactor, RxJava 1, RxJava 2 types, {@link CompletableFuture}, and Java 9+
44-
* Flow.Publisher.
44+
* {@code Flow.Publisher}.
4545
*
4646
* @author Rossen Stoyanchev
4747
* @author Sebastien Deleuze
@@ -54,15 +54,14 @@ public class ReactiveAdapterRegistry {
5454

5555
private final boolean reactorPresent;
5656

57-
private final List<ReactiveAdapter> adapters = new ArrayList<>(32);
57+
private final List<ReactiveAdapter> adapters = new ArrayList<>();
5858

5959

6060
/**
6161
* Create a registry and auto-register default adapters.
6262
* @see #getSharedInstance()
6363
*/
6464
public ReactiveAdapterRegistry() {
65-
6665
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
6766

6867
// Reactor
@@ -104,8 +103,8 @@ public boolean hasAdapters() {
104103

105104
/**
106105
* Register a reactive type along with functions to adapt to and from a
107-
* Reactive Streams {@link Publisher}. The functions can assume their
108-
* input is never be {@code null} nor {@link Optional}.
106+
* Reactive Streams {@link Publisher}. The function arguments assume that
107+
* their input is neither {@code null} nor {@link Optional}.
109108
*/
110109
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
111110
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
@@ -120,6 +119,7 @@ public void registerReactiveType(ReactiveTypeDescriptor descriptor,
120119

121120
/**
122121
* Get the adapter for the given reactive type.
122+
* @return the corresponding adapter, or {@code null} if none available
123123
*/
124124
@Nullable
125125
public ReactiveAdapter getAdapter(Class<?> reactiveType) {
@@ -133,34 +133,41 @@ public ReactiveAdapter getAdapter(Class<?> reactiveType) {
133133
* (may be {@code null} if a concrete source object is given)
134134
* @param source an instance of the reactive type
135135
* (i.e. to adapt from; may be {@code null} if the reactive type is specified)
136+
* @return the corresponding adapter, or {@code null} if none available
136137
*/
137138
@Nullable
138139
public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Object source) {
140+
if (this.adapters.isEmpty()) {
141+
return null;
142+
}
143+
139144
Object sourceToUse = (source instanceof Optional ? ((Optional<?>) source).orElse(null) : source);
140145
Class<?> clazz = (sourceToUse != null ? sourceToUse.getClass() : reactiveType);
141146
if (clazz == null) {
142147
return null;
143148
}
144-
145-
return this.adapters.stream()
146-
.filter(adapter -> adapter.getReactiveType() == clazz)
147-
.findFirst()
148-
.orElseGet(() ->
149-
this.adapters.stream()
150-
.filter(adapter -> adapter.getReactiveType().isAssignableFrom(clazz))
151-
.findFirst()
152-
.orElse(null));
149+
for (ReactiveAdapter adapter : this.adapters) {
150+
if (adapter.getReactiveType() == clazz) {
151+
return adapter;
152+
}
153+
}
154+
for (ReactiveAdapter adapter : this.adapters) {
155+
if (adapter.getReactiveType().isAssignableFrom(clazz)) {
156+
return adapter;
157+
}
158+
}
159+
return null;
153160
}
154161

155162

156163
/**
157-
* Return a shared default {@code ReactiveAdapterRegistry} instance, lazily
158-
* building it once needed.
164+
* Return a shared default {@code ReactiveAdapterRegistry} instance,
165+
* lazily building it once needed.
159166
* <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured
160167
* {@code ReactiveAdapterRegistry} instance for customization purposes.
161168
* This accessor is only meant as a fallback for code paths that want to
162169
* fall back on a default instance if one isn't provided.
163-
* @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null})
170+
* @return the shared {@code ReactiveAdapterRegistry} instance
164171
* @since 5.0.2
165172
*/
166173
public static ReactiveAdapterRegistry getSharedInstance() {

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -76,14 +76,14 @@ class ReactiveTypeHandler {
7676

7777
private static Log logger = LogFactory.getLog(ReactiveTypeHandler.class);
7878

79-
private final ReactiveAdapterRegistry reactiveRegistry;
79+
private final ReactiveAdapterRegistry adapterRegistry;
8080

8181
private final TaskExecutor taskExecutor;
8282

83-
private Boolean taskExecutorWarning;
84-
8583
private final ContentNegotiationManager contentNegotiationManager;
8684

85+
private boolean taskExecutorWarning;
86+
8787

8888
public ReactiveTypeHandler() {
8989
this(ReactiveAdapterRegistry.getSharedInstance(), new SyncTaskExecutor(), new ContentNegotiationManager());
@@ -93,18 +93,20 @@ public ReactiveTypeHandler() {
9393
Assert.notNull(registry, "ReactiveAdapterRegistry is required");
9494
Assert.notNull(executor, "TaskExecutor is required");
9595
Assert.notNull(manager, "ContentNegotiationManager is required");
96-
this.reactiveRegistry = registry;
96+
this.adapterRegistry = registry;
9797
this.taskExecutor = executor;
98-
this.taskExecutorWarning = executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor;
9998
this.contentNegotiationManager = manager;
99+
100+
this.taskExecutorWarning =
101+
(executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor);
100102
}
101103

102104

103105
/**
104106
* Whether the type can be adapted to a Reactive Streams {@link Publisher}.
105107
*/
106108
public boolean isReactiveType(Class<?> type) {
107-
return (this.reactiveRegistry.hasAdapters() && this.reactiveRegistry.getAdapter(type) != null);
109+
return (this.adapterRegistry.getAdapter(type) != null);
108110
}
109111

110112

@@ -119,7 +121,7 @@ public ResponseBodyEmitter handleValue(Object returnValue, MethodParameter retur
119121
ModelAndViewContainer mav, NativeWebRequest request) throws Exception {
120122

121123
Assert.notNull(returnValue, "Expected return value");
122-
ReactiveAdapter adapter = this.reactiveRegistry.getAdapter(returnValue.getClass());
124+
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnValue.getClass());
123125
Assert.state(adapter != null, () -> "Unexpected return value: " + returnValue);
124126

125127
ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric();

0 commit comments

Comments
 (0)