Propagate getFactoryMethod() when using InstanceSupplier.andThen()

Update `InstanceSupplier.andThen` to propagate the result of
`getFactoryMethod()`.

See gh-28748
This commit is contained in:
Phillip Webb 2022-07-20 18:56:57 +01:00
parent 3ae1b9ba57
commit 069d6d3280
2 changed files with 56 additions and 4 deletions

View File

@ -75,8 +75,19 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
default <V> InstanceSupplier<V> andThen( default <V> InstanceSupplier<V> andThen(
ThrowingBiFunction<RegisteredBean, ? super T, ? extends V> after) { ThrowingBiFunction<RegisteredBean, ? super T, ? extends V> after) {
Assert.notNull(after, "After must not be null"); Assert.notNull(after, "After must not be null");
return registeredBean -> after.applyWithException(registeredBean, return new InstanceSupplier<V>() {
get(registeredBean));
@Override
public V get(RegisteredBean registeredBean) throws Exception {
return after.applyWithException(registeredBean, InstanceSupplier.this.get(registeredBean));
}
@Override
public Method getFactoryMethod() {
return InstanceSupplier.this.getFactoryMethod();
}
};
} }
/** /**
@ -94,6 +105,35 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
return registeredBean -> supplier.getWithException(); return registeredBean -> supplier.getWithException();
} }
/**
* Factory method to create an {@link InstanceSupplier} from a
* {@link ThrowingSupplier}.
* @param <T> the type of instance supplied by this supplier
* @param factoryMethod the factory method being used
* @param supplier the source supplier
* @return a new {@link InstanceSupplier}
*/
static <T> InstanceSupplier<T> using(@Nullable Method factoryMethod, ThrowingSupplier<T> supplier) {
Assert.notNull(supplier, "Supplier must not be null");
if (supplier instanceof InstanceSupplier<T> instanceSupplier
&& instanceSupplier.getFactoryMethod() == factoryMethod) {
return instanceSupplier;
}
return new InstanceSupplier<T>() {
@Override
public T get(RegisteredBean registeredBean) throws Exception {
return supplier.getWithException();
}
@Override
public Method getFactoryMethod() {
return factoryMethod;
}
};
}
/** /**
* Lambda friendly method that can be used to create a * Lambda friendly method that can be used to create a
* {@link InstanceSupplier} and add post processors in a single call. For * {@link InstanceSupplier} and add post processors in a single call. For

View File

@ -16,6 +16,8 @@
package org.springframework.beans.factory.support; package org.springframework.beans.factory.support;
import java.lang.reflect.Method;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.util.function.ThrowingBiFunction; import org.springframework.util.function.ThrowingBiFunction;
@ -55,7 +57,7 @@ class InstanceSupplierTests {
} }
@Test @Test
void andThenWithBiFunctionWhenFunctionIsNullThrowsException() { void andThenWhenFunctionIsNullThrowsException() {
InstanceSupplier<String> supplier = registeredBean -> "test"; InstanceSupplier<String> supplier = registeredBean -> "test";
ThrowingBiFunction<RegisteredBean, String, String> after = null; ThrowingBiFunction<RegisteredBean, String, String> after = null;
assertThatIllegalArgumentException().isThrownBy(() -> supplier.andThen(after)) assertThatIllegalArgumentException().isThrownBy(() -> supplier.andThen(after))
@ -63,13 +65,23 @@ class InstanceSupplierTests {
} }
@Test @Test
void andThenWithBiFunctionAppliesFunctionToObtainResult() throws Exception { void andThenAppliesFunctionToObtainResult() throws Exception {
InstanceSupplier<String> supplier = registeredBean -> "bean"; InstanceSupplier<String> supplier = registeredBean -> "bean";
supplier = supplier.andThen( supplier = supplier.andThen(
(registeredBean, string) -> registeredBean.getBeanName() + "-" + string); (registeredBean, string) -> registeredBean.getBeanName() + "-" + string);
assertThat(supplier.get(this.registeredBean)).isEqualTo("test-bean"); assertThat(supplier.get(this.registeredBean)).isEqualTo("test-bean");
} }
@Test
void andThenWhenInstanceSupplierHasFactoryMethod() throws Exception {
Method factoryMethod = getClass().getDeclaredMethod("andThenWhenInstanceSupplierHasFactoryMethod");
InstanceSupplier<String> supplier = InstanceSupplier.using(factoryMethod, () -> "bean");
supplier = supplier.andThen(
(registeredBean, string) -> registeredBean.getBeanName() + "-" + string);
assertThat(supplier.get(this.registeredBean)).isEqualTo("test-bean");
assertThat(supplier.getFactoryMethod()).isSameAs(factoryMethod);
}
@Test @Test
void ofSupplierWhenInstanceSupplierReturnsSameInstance() { void ofSupplierWhenInstanceSupplierReturnsSameInstance() {
InstanceSupplier<String> supplier = registeredBean -> "test"; InstanceSupplier<String> supplier = registeredBean -> "test";