Browse Source

Streamline ReactiveAdapterRegistry.getAdapter usage

Closes gh-22842
pull/23050/head
Juergen Hoeller 7 years ago
parent
commit
bdd9a557a5
  1. 24
      spring-core/src/main/java/org/springframework/core/Conventions.java
  2. 43
      spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java
  3. 18
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -118,13 +118,10 @@ public final class Conventions { @@ -118,13 +118,10 @@ public final class Conventions {
}
else {
valueClass = parameter.getParameterType();
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
if (reactiveAdapterRegistry.hasAdapters()) {
ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass);
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
reactiveSuffix = ClassUtils.getShortName(valueClass);
valueClass = parameter.nested().getNestedParameterType();
}
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(valueClass);
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
reactiveSuffix = ClassUtils.getShortName(valueClass);
valueClass = parameter.nested().getNestedParameterType();
}
}
@ -207,13 +204,10 @@ public final class Conventions { @@ -207,13 +204,10 @@ public final class Conventions {
}
else {
valueClass = resolvedType;
ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
if (reactiveAdapterRegistry.hasAdapters()) {
ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass);
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
reactiveSuffix = ClassUtils.getShortName(valueClass);
valueClass = ResolvableType.forMethodReturnType(method).getGeneric().toClass();
}
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(valueClass);
if (adapter != null && !adapter.getDescriptor().isNoValue()) {
reactiveSuffix = ClassUtils.getShortName(valueClass);
valueClass = ResolvableType.forMethodReturnType(method).getGeneric().toClass();
}
}

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,7 +41,7 @@ import org.springframework.util.ReflectionUtils; @@ -41,7 +41,7 @@ import org.springframework.util.ReflectionUtils;
*
* <p>By default, depending on classpath availability, adapters are registered
* for Reactor, RxJava 1, RxJava 2 types, {@link CompletableFuture}, and Java 9+
* Flow.Publisher.
* {@code Flow.Publisher}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
@ -54,7 +54,7 @@ public class ReactiveAdapterRegistry { @@ -54,7 +54,7 @@ public class ReactiveAdapterRegistry {
private final boolean reactorPresent;
private final List<ReactiveAdapter> adapters = new ArrayList<>(32);
private final List<ReactiveAdapter> adapters = new ArrayList<>();
/**
@ -62,7 +62,6 @@ public class ReactiveAdapterRegistry { @@ -62,7 +62,6 @@ public class ReactiveAdapterRegistry {
* @see #getSharedInstance()
*/
public ReactiveAdapterRegistry() {
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
// Reactor
@ -104,8 +103,8 @@ public class ReactiveAdapterRegistry { @@ -104,8 +103,8 @@ public class ReactiveAdapterRegistry {
/**
* Register a reactive type along with functions to adapt to and from a
* Reactive Streams {@link Publisher}. The functions can assume their
* input is never be {@code null} nor {@link Optional}.
* Reactive Streams {@link Publisher}. The function arguments assume that
* their input is neither {@code null} nor {@link Optional}.
*/
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
@ -120,6 +119,7 @@ public class ReactiveAdapterRegistry { @@ -120,6 +119,7 @@ public class ReactiveAdapterRegistry {
/**
* Get the adapter for the given reactive type.
* @return the corresponding adapter, or {@code null} if none available
*/
@Nullable
public ReactiveAdapter getAdapter(Class<?> reactiveType) {
@ -133,34 +133,41 @@ public class ReactiveAdapterRegistry { @@ -133,34 +133,41 @@ public class ReactiveAdapterRegistry {
* (may be {@code null} if a concrete source object is given)
* @param source an instance of the reactive type
* (i.e. to adapt from; may be {@code null} if the reactive type is specified)
* @return the corresponding adapter, or {@code null} if none available
*/
@Nullable
public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Object source) {
if (this.adapters.isEmpty()) {
return null;
}
Object sourceToUse = (source instanceof Optional ? ((Optional<?>) source).orElse(null) : source);
Class<?> clazz = (sourceToUse != null ? sourceToUse.getClass() : reactiveType);
if (clazz == null) {
return null;
}
return this.adapters.stream()
.filter(adapter -> adapter.getReactiveType() == clazz)
.findFirst()
.orElseGet(() ->
this.adapters.stream()
.filter(adapter -> adapter.getReactiveType().isAssignableFrom(clazz))
.findFirst()
.orElse(null));
for (ReactiveAdapter adapter : this.adapters) {
if (adapter.getReactiveType() == clazz) {
return adapter;
}
}
for (ReactiveAdapter adapter : this.adapters) {
if (adapter.getReactiveType().isAssignableFrom(clazz)) {
return adapter;
}
}
return null;
}
/**
* Return a shared default {@code ReactiveAdapterRegistry} instance, lazily
* building it once needed.
* Return a shared default {@code ReactiveAdapterRegistry} instance,
* lazily building it once needed.
* <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured
* {@code ReactiveAdapterRegistry} instance for customization purposes.
* This accessor is only meant as a fallback for code paths that want to
* fall back on a default instance if one isn't provided.
* @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null})
* @return the shared {@code ReactiveAdapterRegistry} instance
* @since 5.0.2
*/
public static ReactiveAdapterRegistry getSharedInstance() {

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -76,14 +76,14 @@ class ReactiveTypeHandler { @@ -76,14 +76,14 @@ class ReactiveTypeHandler {
private static Log logger = LogFactory.getLog(ReactiveTypeHandler.class);
private final ReactiveAdapterRegistry reactiveRegistry;
private final ReactiveAdapterRegistry adapterRegistry;
private final TaskExecutor taskExecutor;
private Boolean taskExecutorWarning;
private final ContentNegotiationManager contentNegotiationManager;
private boolean taskExecutorWarning;
public ReactiveTypeHandler() {
this(ReactiveAdapterRegistry.getSharedInstance(), new SyncTaskExecutor(), new ContentNegotiationManager());
@ -93,10 +93,12 @@ class ReactiveTypeHandler { @@ -93,10 +93,12 @@ class ReactiveTypeHandler {
Assert.notNull(registry, "ReactiveAdapterRegistry is required");
Assert.notNull(executor, "TaskExecutor is required");
Assert.notNull(manager, "ContentNegotiationManager is required");
this.reactiveRegistry = registry;
this.adapterRegistry = registry;
this.taskExecutor = executor;
this.taskExecutorWarning = executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor;
this.contentNegotiationManager = manager;
this.taskExecutorWarning =
(executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor);
}
@ -104,7 +106,7 @@ class ReactiveTypeHandler { @@ -104,7 +106,7 @@ class ReactiveTypeHandler {
* Whether the type can be adapted to a Reactive Streams {@link Publisher}.
*/
public boolean isReactiveType(Class<?> type) {
return (this.reactiveRegistry.hasAdapters() && this.reactiveRegistry.getAdapter(type) != null);
return (this.adapterRegistry.getAdapter(type) != null);
}
@ -119,7 +121,7 @@ class ReactiveTypeHandler { @@ -119,7 +121,7 @@ class ReactiveTypeHandler {
ModelAndViewContainer mav, NativeWebRequest request) throws Exception {
Assert.notNull(returnValue, "Expected return value");
ReactiveAdapter adapter = this.reactiveRegistry.getAdapter(returnValue.getClass());
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnValue.getClass());
Assert.state(adapter != null, () -> "Unexpected return value: " + returnValue);
ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric();

Loading…
Cancel
Save