|
|
|
|
@ -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() { |
|
|
|
|
|