Polishing

This commit is contained in:
Juergen Hoeller
2021-09-24 13:49:48 +02:00
parent ebd351753f
commit 195d375964
4 changed files with 43 additions and 48 deletions

View File

@@ -34,8 +34,8 @@ dependencies {
testCompile("org.codehaus.groovy:groovy-test")
testCompile("org.codehaus.groovy:groovy-xml")
testCompile("org.apache.commons:commons-pool2")
testCompile("javax.inject:javax.inject-tck")
testCompile("org.awaitility:awaitility")
testCompile("javax.inject:javax.inject-tck")
testRuntime("javax.xml.bind:jaxb-api")
testRuntime("org.glassfish:javax.el")
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)

View File

@@ -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");
* 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;
/**
* 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
@@ -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
* 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
* the factory is the caller or not.
*

View File

@@ -53,22 +53,22 @@ dependencies {
optional("io.reactivex:rxjava-reactive-streams")
optional("io.reactivex.rxjava2:rxjava")
optional("io.netty:netty-buffer")
testCompile("io.projectreactor:reactor-test")
testCompile("com.google.code.findbugs:jsr305")
testCompile(project(":kotlin-coroutines"))
testCompile("javax.annotation:javax.annotation-api")
testCompile("javax.xml.bind:jaxb-api")
testCompile("com.google.code.findbugs:jsr305")
testCompile("com.fasterxml.woodstox:woodstox-core")
testCompile("org.xmlunit:xmlunit-assertj")
testCompile("org.xmlunit:xmlunit-matchers")
testCompile(project(":kotlin-coroutines"))
testCompile("io.projectreactor:reactor-test")
testCompile("io.projectreactor.tools:blockhound")
testFixturesImplementation("io.projectreactor:reactor-test")
testFixturesImplementation("com.google.code.findbugs:jsr305")
testFixturesImplementation("org.junit.platform:junit-platform-launcher")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params")
testFixturesImplementation("org.assertj:assertj-core")
testFixturesImplementation("org.xmlunit:xmlunit-assertj")
testFixturesImplementation("io.projectreactor:reactor-test")
}
jar {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -47,7 +47,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}, Java 9+
* {@code Flow.Publisher} and Kotlin Coroutines {@code Deferred} and {@code Flow}.
* {@code Flow.Publisher}, and Kotlin Coroutines {@code Deferred} and {@code Flow}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
@@ -74,6 +74,10 @@ public class ReactiveAdapterRegistry {
boolean reactorRegistered = false;
if (ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader)) {
new ReactorRegistrar().registerAdapters(this);
if (ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader)) {
// Java 9+ Flow.Publisher
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
}
reactorRegistered = true;
}
this.reactorPresent = reactorRegistered;
@@ -83,20 +87,12 @@ public class ReactiveAdapterRegistry {
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader)) {
new RxJava1Registrar().registerAdapters(this);
}
// RxJava2
if (ClassUtils.isPresent("io.reactivex.Flowable", classLoader)) {
new RxJava2Registrar().registerAdapters(this);
}
// Java 9+ Flow.Publisher
if (ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader)) {
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
}
// If not present, do nothing for the time being...
// We can fall back on "reactive-streams-flow-bridge" (once released)
// Coroutines
// Kotlin Coroutines
if (this.reactorPresent && ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader)) {
new CoroutinesRegistrar().registerAdapters(this);
}
@@ -226,6 +222,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 {
void registerAdapters(ReactiveAdapterRegistry registry) {
@@ -280,35 +305,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
* {@link Mono} depending on {@link ReactiveTypeDescriptor#isMultiValue()}.