Add registerReactiveTypeOverride method to ReactiveAdapterRegistry
Closes gh-31047
This commit is contained in:
parent
6f2a13fafd
commit
389238f622
|
|
@ -105,16 +105,45 @@ public class ReactiveAdapterRegistry {
|
||||||
* Register a reactive type along with functions to adapt to and from a
|
* Register a reactive type along with functions to adapt to and from a
|
||||||
* Reactive Streams {@link Publisher}. The function arguments assume that
|
* Reactive Streams {@link Publisher}. The function arguments assume that
|
||||||
* their input is neither {@code null} nor {@link Optional}.
|
* their input is neither {@code null} nor {@link Optional}.
|
||||||
|
* <p>This variant registers the new adapter after existing adapters.
|
||||||
|
* It will be matched for the exact reactive type if no earlier adapter was
|
||||||
|
* registered for the specific type, and it will be matched for assignability
|
||||||
|
* in a second pass if no earlier adapter had an assignable type before.
|
||||||
|
* @see #registerReactiveTypeOverride
|
||||||
|
* @see #getAdapter
|
||||||
*/
|
*/
|
||||||
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
|
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
|
||||||
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
|
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
|
||||||
|
|
||||||
if (reactorPresent) {
|
this.adapters.add(buildAdapter(descriptor, toAdapter, fromAdapter));
|
||||||
this.adapters.add(new ReactorAdapter(descriptor, toAdapter, fromAdapter));
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.adapters.add(new ReactiveAdapter(descriptor, toAdapter, fromAdapter));
|
/**
|
||||||
|
* Register a reactive type along with functions to adapt to and from a
|
||||||
|
* Reactive Streams {@link Publisher}. The function arguments assume that
|
||||||
|
* their input is neither {@code null} nor {@link Optional}.
|
||||||
|
* <p>This variant registers the new adapter first, effectively overriding
|
||||||
|
* any previously registered adapters for the same reactive type. This allows
|
||||||
|
* for overriding existing adapters, in particular default adapters.
|
||||||
|
* <p>Note that existing adapters for specific types will still match before
|
||||||
|
* an assignability match with the new adapter. In order to override all
|
||||||
|
* existing matches, a new reactive type adapter needs to be registered
|
||||||
|
* for every specific type, not relying on subtype assignability matches.
|
||||||
|
* @since 5.3.30
|
||||||
|
* @see #registerReactiveType
|
||||||
|
* @see #getAdapter
|
||||||
|
*/
|
||||||
|
public void registerReactiveTypeOverride(ReactiveTypeDescriptor descriptor,
|
||||||
|
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
|
||||||
|
|
||||||
|
this.adapters.add(0, buildAdapter(descriptor, toAdapter, fromAdapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ReactiveAdapter buildAdapter(ReactiveTypeDescriptor descriptor,
|
||||||
|
Function<Object, Publisher<?>> toAdapter, Function<Publisher<?>, Object> fromAdapter) {
|
||||||
|
|
||||||
|
return (reactorPresent ? new ReactorAdapter(descriptor, toAdapter, fromAdapter) :
|
||||||
|
new ReactiveAdapter(descriptor, toAdapter, fromAdapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Unit tests for {@link ReactiveAdapterRegistry}.
|
* Unit tests for {@link ReactiveAdapterRegistry}.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Juergen Hoeller
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
class ReactiveAdapterRegistryTests {
|
class ReactiveAdapterRegistryTests {
|
||||||
|
|
@ -54,14 +55,40 @@ class ReactiveAdapterRegistryTests {
|
||||||
ReactiveAdapter adapter2 = getAdapter(ExtendedFlux.class);
|
ReactiveAdapter adapter2 = getAdapter(ExtendedFlux.class);
|
||||||
assertThat(adapter2).isSameAs(adapter1);
|
assertThat(adapter2).isSameAs(adapter1);
|
||||||
|
|
||||||
|
// Register regular reactive type (after existing adapters)
|
||||||
this.registry.registerReactiveType(
|
this.registry.registerReactiveType(
|
||||||
ReactiveTypeDescriptor.multiValue(ExtendedFlux.class, ExtendedFlux::empty),
|
ReactiveTypeDescriptor.multiValue(ExtendedFlux.class, ExtendedFlux::empty),
|
||||||
o -> (ExtendedFlux<?>) o,
|
o -> (ExtendedFlux<?>) o,
|
||||||
ExtendedFlux::from);
|
ExtendedFlux::from);
|
||||||
|
|
||||||
|
// Matches for ExtendedFlux itself
|
||||||
ReactiveAdapter adapter3 = getAdapter(ExtendedFlux.class);
|
ReactiveAdapter adapter3 = getAdapter(ExtendedFlux.class);
|
||||||
assertThat(adapter3).isNotNull();
|
assertThat(adapter3).isNotNull();
|
||||||
assertThat(adapter3).isNotSameAs(adapter1);
|
assertThat(adapter3).isNotSameAs(adapter1);
|
||||||
|
|
||||||
|
// Does not match for ExtendedFlux subclass since the default Flux adapter
|
||||||
|
// is being assignability-checked first when no specific match was found
|
||||||
|
ReactiveAdapter adapter4 = getAdapter(ExtendedExtendedFlux.class);
|
||||||
|
assertThat(adapter4).isSameAs(adapter1);
|
||||||
|
|
||||||
|
// Register reactive type override (before existing adapters)
|
||||||
|
this.registry.registerReactiveTypeOverride(
|
||||||
|
ReactiveTypeDescriptor.multiValue(Flux.class, ExtendedFlux::empty),
|
||||||
|
o -> (ExtendedFlux<?>) o,
|
||||||
|
ExtendedFlux::from);
|
||||||
|
|
||||||
|
// Override match for Flux
|
||||||
|
ReactiveAdapter adapter5 = getAdapter(Flux.class);
|
||||||
|
assertThat(adapter5).isNotNull();
|
||||||
|
assertThat(adapter5).isNotSameAs(adapter1);
|
||||||
|
|
||||||
|
// Initially registered adapter specifically matches for ExtendedFlux
|
||||||
|
ReactiveAdapter adapter6 = getAdapter(ExtendedFlux.class);
|
||||||
|
assertThat(adapter6).isSameAs(adapter3);
|
||||||
|
|
||||||
|
// Override match for ExtendedFlux subclass
|
||||||
|
ReactiveAdapter adapter7 = getAdapter(ExtendedExtendedFlux.class);
|
||||||
|
assertThat(adapter7).isSameAs(adapter5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -81,6 +108,10 @@ class ReactiveAdapterRegistryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class ExtendedExtendedFlux<T> extends ExtendedFlux<T> {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class Reactor {
|
class Reactor {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue