Browse Source

Polishing

pull/27555/head
Juergen Hoeller 3 years ago
parent
commit
1f8c233dfc
  1. 2
      spring-context/spring-context.gradle
  2. 5
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostConstructAndAutowiringTests.java
  3. 72
      spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java

2
spring-context/spring-context.gradle

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

5
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostConstructAndAutowiringTests.java

@ -1,5 +1,5 @@ @@ -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; @@ -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; @@ -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.
*

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

@ -77,11 +77,11 @@ public class ReactiveAdapterRegistry { @@ -77,11 +77,11 @@ public class ReactiveAdapterRegistry {
static {
ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader();
reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader);
flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader);
rxjava1Present = ClassUtils.isPresent("rx.Observable", classLoader) &&
ClassUtils.isPresent("rx.RxReactiveStreams", classLoader);
rxjava2Present = ClassUtils.isPresent("io.reactivex.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);
mutinyPresent = ClassUtils.isPresent("io.smallrye.mutiny.Multi", classLoader);
}
@ -97,13 +97,16 @@ public class ReactiveAdapterRegistry { @@ -97,13 +97,16 @@ public class ReactiveAdapterRegistry {
// Reactor
if (reactorPresent) {
new ReactorRegistrar().registerAdapters(this);
if (flowPublisherPresent) {
// Java 9+ Flow.Publisher
new ReactorJdkFlowAdapterRegistrar().registerAdapter(this);
}
}
// RxJava1 (deprecated)
if (rxjava1Present) {
new RxJava1Registrar().registerAdapters(this);
}
// RxJava2
if (rxjava2Present) {
new RxJava2Registrar().registerAdapters(this);
@ -113,13 +116,6 @@ public class ReactiveAdapterRegistry { @@ -113,13 +116,6 @@ public class ReactiveAdapterRegistry {
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
if (reactorPresent && kotlinCoroutinesPresent) {
new CoroutinesRegistrar().registerAdapters(this);
@ -253,6 +249,35 @@ public class ReactiveAdapterRegistry { @@ -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 {
void registerAdapters(ReactiveAdapterRegistry registry) {
@ -307,6 +332,7 @@ public class ReactiveAdapterRegistry { @@ -307,6 +332,7 @@ public class ReactiveAdapterRegistry {
}
}
private static class RxJava3Registrar {
void registerAdapters(ReactiveAdapterRegistry registry) {
@ -347,34 +373,6 @@ public class ReactiveAdapterRegistry { @@ -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

Loading…
Cancel
Save