Polishing
This commit is contained in:
parent
0dc5d2794f
commit
1f8c233dfc
|
@ -34,8 +34,8 @@ dependencies {
|
||||||
testImplementation("org.codehaus.groovy:groovy-test")
|
testImplementation("org.codehaus.groovy:groovy-test")
|
||||||
testImplementation("org.codehaus.groovy:groovy-xml")
|
testImplementation("org.codehaus.groovy:groovy-xml")
|
||||||
testImplementation("org.apache.commons:commons-pool2")
|
testImplementation("org.apache.commons:commons-pool2")
|
||||||
testImplementation("javax.inject:javax.inject-tck")
|
|
||||||
testImplementation("org.awaitility:awaitility")
|
testImplementation("org.awaitility:awaitility")
|
||||||
|
testImplementation("javax.inject:javax.inject-tck")
|
||||||
testRuntimeOnly("javax.xml.bind:jaxb-api")
|
testRuntimeOnly("javax.xml.bind:jaxb-api")
|
||||||
testRuntimeOnly("org.glassfish:javax.el")
|
testRuntimeOnly("org.glassfish:javax.el")
|
||||||
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)
|
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,7 +25,6 @@ import org.springframework.beans.testfixture.beans.TestBean;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests cornering the issue reported in SPR-8080. If the product of a @Bean method
|
* Tests cornering the issue reported in SPR-8080. If the product of a @Bean method
|
||||||
* was @Autowired into a configuration class while at the same time the declaring
|
* was @Autowired into a configuration class while at the same time the declaring
|
||||||
|
@ -34,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* 'currently in creation' status of the autowired bean and result in creating multiple
|
* 'currently in creation' status of the autowired bean and result in creating multiple
|
||||||
* instances of the given @Bean, violating container scoping / singleton semantics.
|
* instances of the given @Bean, violating container scoping / singleton semantics.
|
||||||
*
|
*
|
||||||
* This is resolved through no longer relying on 'currently in creation' status, but
|
* <p>This is resolved through no longer relying on 'currently in creation' status, but
|
||||||
* rather on a thread local that informs the enhanced bean method implementation whether
|
* rather on a thread local that informs the enhanced bean method implementation whether
|
||||||
* the factory is the caller or not.
|
* the factory is the caller or not.
|
||||||
*
|
*
|
||||||
|
|
|
@ -77,11 +77,11 @@ public class ReactiveAdapterRegistry {
|
||||||
static {
|
static {
|
||||||
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
|
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
|
||||||
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
|
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
|
||||||
|
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
|
||||||
rxjava1Present = ClassUtils.isPresent("rx.Observable", classLoader) &&
|
rxjava1Present = ClassUtils.isPresent("rx.Observable", classLoader) &&
|
||||||
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader);
|
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader);
|
||||||
rxjava2Present = ClassUtils.isPresent("io.reactivex.Flowable", classLoader);
|
rxjava2Present = ClassUtils.isPresent("io.reactivex.Flowable", classLoader);
|
||||||
rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader);
|
rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader);
|
||||||
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
|
|
||||||
kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader);
|
kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader);
|
||||||
mutinyPresent = ClassUtils.isPresent("io.smallrye.mutiny.Multi", classLoader);
|
mutinyPresent = ClassUtils.isPresent("io.smallrye.mutiny.Multi", classLoader);
|
||||||
}
|
}
|
||||||
|
@ -97,13 +97,16 @@ public class ReactiveAdapterRegistry {
|
||||||
// Reactor
|
// Reactor
|
||||||
if (reactorPresent) {
|
if (reactorPresent) {
|
||||||
new ReactorRegistrar().registerAdapters(this);
|
new ReactorRegistrar().registerAdapters(this);
|
||||||
|
if (flowPublisherPresent) {
|
||||||
|
// Java 9+ Flow.Publisher
|
||||||
|
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RxJava1 (deprecated)
|
// RxJava1 (deprecated)
|
||||||
if (rxjava1Present) {
|
if (rxjava1Present) {
|
||||||
new RxJava1Registrar().registerAdapters(this);
|
new RxJava1Registrar().registerAdapters(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RxJava2
|
// RxJava2
|
||||||
if (rxjava2Present) {
|
if (rxjava2Present) {
|
||||||
new RxJava2Registrar().registerAdapters(this);
|
new RxJava2Registrar().registerAdapters(this);
|
||||||
|
@ -113,13 +116,6 @@ public class ReactiveAdapterRegistry {
|
||||||
new RxJava3Registrar().registerAdapters(this);
|
new RxJava3Registrar().registerAdapters(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Java 9+ Flow.Publisher
|
|
||||||
if (flowPublisherPresent) {
|
|
||||||
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
|
|
||||||
}
|
|
||||||
// If not present, do nothing for the time being...
|
|
||||||
// We can fall back on "reactive-streams-flow-bridge" (once released)
|
|
||||||
|
|
||||||
// Kotlin Coroutines
|
// Kotlin Coroutines
|
||||||
if (reactorPresent && kotlinCoroutinesPresent) {
|
if (reactorPresent && kotlinCoroutinesPresent) {
|
||||||
new CoroutinesRegistrar().registerAdapters(this);
|
new CoroutinesRegistrar().registerAdapters(this);
|
||||||
|
@ -253,6 +249,35 @@ public class ReactiveAdapterRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class ReactorJdkFlowAdapterRegistrar {
|
||||||
|
|
||||||
|
void registerAdapter(ReactiveAdapterRegistry registry) {
|
||||||
|
// Reflectively access optional JDK 9+ API (for runtime compatibility with JDK 8)
|
||||||
|
|
||||||
|
try {
|
||||||
|
String publisherName = "java.util.concurrent.Flow.Publisher";
|
||||||
|
Class<?> publisherClass = ClassUtils.forName(publisherName, getClass().getClassLoader());
|
||||||
|
|
||||||
|
String adapterName = "reactor.adapter.JdkFlowAdapter";
|
||||||
|
Class<?> flowAdapterClass = ClassUtils.forName(adapterName, getClass().getClassLoader());
|
||||||
|
|
||||||
|
Method toFluxMethod = flowAdapterClass.getMethod("flowPublisherToFlux", publisherClass);
|
||||||
|
Method toFlowMethod = flowAdapterClass.getMethod("publisherToFlowPublisher", Publisher.class);
|
||||||
|
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
|
||||||
|
|
||||||
|
registry.registerReactiveType(
|
||||||
|
ReactiveTypeDescriptor.multiValue(publisherClass, () -> emptyFlow),
|
||||||
|
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
|
||||||
|
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class RxJava1Registrar {
|
private static class RxJava1Registrar {
|
||||||
|
|
||||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||||
|
@ -307,6 +332,7 @@ public class ReactiveAdapterRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class RxJava3Registrar {
|
private static class RxJava3Registrar {
|
||||||
|
|
||||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||||
|
@ -347,34 +373,6 @@ public class ReactiveAdapterRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ReactorJdkFlowAdapterRegistrar {
|
|
||||||
|
|
||||||
void registerAdapter(ReactiveAdapterRegistry registry) {
|
|
||||||
// TODO: remove reflection when build requires JDK 9+
|
|
||||||
|
|
||||||
try {
|
|
||||||
String publisherName = "java.util.concurrent.Flow.Publisher";
|
|
||||||
Class<?> publisherClass = ClassUtils.forName(publisherName, getClass().getClassLoader());
|
|
||||||
|
|
||||||
String adapterName = "reactor.adapter.JdkFlowAdapter";
|
|
||||||
Class<?> flowAdapterClass = ClassUtils.forName(adapterName, getClass().getClassLoader());
|
|
||||||
|
|
||||||
Method toFluxMethod = flowAdapterClass.getMethod("flowPublisherToFlux", publisherClass);
|
|
||||||
Method toFlowMethod = flowAdapterClass.getMethod("publisherToFlowPublisher", Publisher.class);
|
|
||||||
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
|
|
||||||
|
|
||||||
registry.registerReactiveType(
|
|
||||||
ReactiveTypeDescriptor.multiValue(publisherClass, () -> emptyFlow),
|
|
||||||
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
|
|
||||||
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReactiveAdapter variant that wraps adapted Publishers as {@link Flux} or
|
* ReactiveAdapter variant that wraps adapted Publishers as {@link Flux} or
|
||||||
|
|
Loading…
Reference in New Issue