Pass pre-determined merged bean definition into InstanceSupplier (for inner beans)
Replaces useless protected obtainFromSupplier method with obtainInstanceFromSupplier. Moves InstanceSupplier handling to appropriate subclass (DefaultListableBeanFactory). BeanInstanceSupplier throws BeanInstantiationException instead of BeanCreationException. Closes gh-29803
This commit is contained in:
parent
6cd67412cc
commit
95710646d1
|
|
@ -27,9 +27,9 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
|
@ -97,11 +97,13 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
private BeanInstanceSupplier(ExecutableLookup lookup,
|
||||
@Nullable ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator,
|
||||
@Nullable String[] shortcuts) {
|
||||
|
||||
this.lookup = lookup;
|
||||
this.generator = generator;
|
||||
this.shortcuts = shortcuts;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link BeanInstanceSupplier} that resolves
|
||||
* arguments for the specified bean constructor.
|
||||
|
|
@ -109,9 +111,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
* @param parameterTypes the constructor parameter types
|
||||
* @return a new {@link BeanInstanceSupplier} instance
|
||||
*/
|
||||
public static <T> BeanInstanceSupplier<T> forConstructor(
|
||||
Class<?>... parameterTypes) {
|
||||
|
||||
public static <T> BeanInstanceSupplier<T> forConstructor(Class<?>... parameterTypes) {
|
||||
Assert.notNull(parameterTypes, "'parameterTypes' must not be null");
|
||||
Assert.noNullElements(parameterTypes, "'parameterTypes' must not contain null elements");
|
||||
return new BeanInstanceSupplier<>(new ConstructorLookup(parameterTypes), null, null);
|
||||
|
|
@ -149,11 +149,11 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
* @param generator a {@link ThrowingBiFunction} that uses the
|
||||
* {@link RegisteredBean} and resolved {@link AutowiredArguments} to
|
||||
* instantiate the underlying bean
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified
|
||||
* generator
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
|
||||
*/
|
||||
public BeanInstanceSupplier<T> withGenerator(
|
||||
ThrowingBiFunction<RegisteredBean, AutowiredArguments, T> generator) {
|
||||
|
||||
Assert.notNull(generator, "'generator' must not be null");
|
||||
return new BeanInstanceSupplier<>(this.lookup, generator, this.shortcuts);
|
||||
}
|
||||
|
|
@ -163,11 +163,9 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
* {@code generator} function to instantiate the underlying bean.
|
||||
* @param generator a {@link ThrowingFunction} that uses the
|
||||
* {@link RegisteredBean} to instantiate the underlying bean
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified
|
||||
* generator
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
|
||||
*/
|
||||
public BeanInstanceSupplier<T> withGenerator(
|
||||
ThrowingFunction<RegisteredBean, T> generator) {
|
||||
public BeanInstanceSupplier<T> withGenerator(ThrowingFunction<RegisteredBean, T> generator) {
|
||||
Assert.notNull(generator, "'generator' must not be null");
|
||||
return new BeanInstanceSupplier<>(this.lookup,
|
||||
(registeredBean, args) -> generator.apply(registeredBean), this.shortcuts);
|
||||
|
|
@ -176,10 +174,8 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
/**
|
||||
* Return a new {@link BeanInstanceSupplier} instance that uses the specified
|
||||
* {@code generator} supplier to instantiate the underlying bean.
|
||||
* @param generator a {@link ThrowingSupplier} to instantiate the underlying
|
||||
* bean
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified
|
||||
* generator
|
||||
* @param generator a {@link ThrowingSupplier} to instantiate the underlying bean
|
||||
* @return a new {@link BeanInstanceSupplier} instance with the specified generator
|
||||
*/
|
||||
public BeanInstanceSupplier<T> withGenerator(ThrowingSupplier<T> generator) {
|
||||
Assert.notNull(generator, "'generator' must not be null");
|
||||
|
|
@ -282,8 +278,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
if (executable instanceof Method method) {
|
||||
return new MethodParameter(method, index);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Unsupported executable " + executable.getClass().getName());
|
||||
throw new IllegalStateException("Unsupported executable: " + executable.getClass().getName());
|
||||
}
|
||||
|
||||
private ConstructorArgumentValues resolveArgumentValues(
|
||||
|
|
@ -303,9 +298,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
return resolved;
|
||||
}
|
||||
|
||||
private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver,
|
||||
ValueHolder valueHolder) {
|
||||
|
||||
private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver, ValueHolder valueHolder) {
|
||||
if (valueHolder.isConverted()) {
|
||||
return valueHolder;
|
||||
}
|
||||
|
|
@ -331,8 +324,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
}
|
||||
try {
|
||||
try {
|
||||
return beanFactory.resolveDependency(dependencyDescriptor, beanName,
|
||||
autowiredBeans, typeConverter);
|
||||
return beanFactory.resolveDependency(dependencyDescriptor, beanName, autowiredBeans, typeConverter);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
if (parameterType.isArray()) {
|
||||
|
|
@ -348,47 +340,45 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
}
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
throw new UnsatisfiedDependencyException(null, beanName,
|
||||
new InjectionPoint(parameter), ex);
|
||||
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(parameter), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable,
|
||||
Object[] arguments) {
|
||||
|
||||
try {
|
||||
private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable, Object[] args) {
|
||||
if (executable instanceof Constructor<?> constructor) {
|
||||
return (T) instantiate(constructor, arguments);
|
||||
}
|
||||
if (executable instanceof Method method) {
|
||||
return (T) instantiate(beanFactory, method, arguments);
|
||||
}
|
||||
try {
|
||||
return (T) instantiate(constructor, args);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BeanCreationException(
|
||||
"Unable to instantiate bean using " + executable, ex);
|
||||
throw new BeanInstantiationException(constructor, ex.getMessage(), ex);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Unsupported executable " + executable.getClass().getName());
|
||||
}
|
||||
if (executable instanceof Method method) {
|
||||
try {
|
||||
return (T) instantiate(beanFactory, method, args);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BeanInstantiationException(method, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Unsupported executable " + executable.getClass().getName());
|
||||
}
|
||||
|
||||
private Object instantiate(Constructor<?> constructor, Object[] arguments) throws Exception {
|
||||
private Object instantiate(Constructor<?> constructor, Object[] args) throws Exception {
|
||||
Class<?> declaringClass = constructor.getDeclaringClass();
|
||||
if (ClassUtils.isInnerClass(declaringClass)) {
|
||||
Object enclosingInstance = createInstance(declaringClass.getEnclosingClass());
|
||||
arguments = ObjectUtils.addObjectToArray(arguments, enclosingInstance, 0);
|
||||
args = ObjectUtils.addObjectToArray(args, enclosingInstance, 0);
|
||||
}
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
return constructor.newInstance(arguments);
|
||||
return constructor.newInstance(args);
|
||||
}
|
||||
|
||||
private Object instantiate(ConfigurableBeanFactory beanFactory, Method method,
|
||||
Object[] arguments) {
|
||||
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
private Object instantiate(ConfigurableBeanFactory beanFactory, Method method, Object[] args) throws Exception {
|
||||
Object target = getFactoryMethodTarget(beanFactory, method);
|
||||
return ReflectionUtils.invokeMethod(method, target, arguments);
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
return method.invoke(target, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
@ -416,13 +406,13 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
return Arrays.stream(parameterTypes).map(Class::getName).collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs lookup of the {@link Executable}.
|
||||
*/
|
||||
static abstract class ExecutableLookup {
|
||||
|
||||
abstract Executable get(RegisteredBean registeredBean);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -433,12 +423,10 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
|
||||
ConstructorLookup(Class<?>[] parameterTypes) {
|
||||
this.parameterTypes = parameterTypes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Executable get(RegisteredBean registeredBean) {
|
||||
Class<?> beanClass = registeredBean.getBeanClass();
|
||||
|
|
@ -456,10 +444,8 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Constructor with parameter types [%s]".formatted(
|
||||
toCommaSeparatedNames(this.parameterTypes));
|
||||
return "Constructor with parameter types [%s]".formatted(toCommaSeparatedNames(this.parameterTypes));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -474,23 +460,19 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
|
||||
FactoryMethodLookup(Class<?> declaringClass, String methodName,
|
||||
Class<?>[] parameterTypes) {
|
||||
FactoryMethodLookup(Class<?> declaringClass, String methodName, Class<?>[] parameterTypes) {
|
||||
this.declaringClass = declaringClass;
|
||||
this.methodName = methodName;
|
||||
this.parameterTypes = parameterTypes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Executable get(RegisteredBean registeredBean) {
|
||||
return get();
|
||||
}
|
||||
|
||||
Method get() {
|
||||
Method method = ReflectionUtils.findMethod(this.declaringClass,
|
||||
this.methodName, this.parameterTypes);
|
||||
Method method = ReflectionUtils.findMethod(this.declaringClass, this.methodName, this.parameterTypes);
|
||||
Assert.notNull(method, () -> "%s cannot be found".formatted(this));
|
||||
return method;
|
||||
}
|
||||
|
|
@ -501,7 +483,6 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
|
|||
this.methodName, toCommaSeparatedNames(this.parameterTypes),
|
||||
this.declaringClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ import org.springframework.beans.factory.config.AutowiredPropertyMarker;
|
|||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
|
||||
|
|
@ -1154,7 +1153,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
|
||||
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
|
||||
if (instanceSupplier != null) {
|
||||
return obtainFromSupplier(instanceSupplier, beanName);
|
||||
return obtainFromSupplier(instanceSupplier, beanName, mbd);
|
||||
}
|
||||
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
|
|
@ -1203,38 +1202,20 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
* @param supplier the configured supplier
|
||||
* @param beanName the corresponding bean name
|
||||
* @return a BeanWrapper for the new instance
|
||||
* @since 5.0
|
||||
* @see #getObjectForBeanInstance
|
||||
*/
|
||||
protected BeanWrapper obtainFromSupplier(Supplier<?> supplier, String beanName) {
|
||||
Object instance = obtainInstanceFromSupplier(supplier, beanName);
|
||||
if (instance == null) {
|
||||
instance = new NullBean();
|
||||
}
|
||||
BeanWrapper bw = new BeanWrapperImpl(instance);
|
||||
initBeanWrapper(bw);
|
||||
return bw;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName) {
|
||||
private BeanWrapper obtainFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd) {
|
||||
String outerBean = this.currentlyCreatedBean.get();
|
||||
this.currentlyCreatedBean.set(beanName);
|
||||
Object instance;
|
||||
|
||||
try {
|
||||
if (supplier instanceof InstanceSupplier<?> instanceSupplier) {
|
||||
return instanceSupplier.get(RegisteredBean.of((ConfigurableListableBeanFactory) this, beanName));
|
||||
}
|
||||
if (supplier instanceof ThrowingSupplier<?> throwingSupplier) {
|
||||
return throwingSupplier.getWithException();
|
||||
}
|
||||
return supplier.get();
|
||||
instance = obtainInstanceFromSupplier(supplier, beanName, mbd);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (ex instanceof BeansException beansException) {
|
||||
throw beansException;
|
||||
}
|
||||
throw new BeanCreationException(beanName,
|
||||
"Instantiation of supplied bean failed", ex);
|
||||
throw new BeanCreationException(beanName, "Instantiation of supplied bean failed", ex);
|
||||
}
|
||||
finally {
|
||||
if (outerBean != null) {
|
||||
|
|
@ -1244,6 +1225,31 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
this.currentlyCreatedBean.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (instance == null) {
|
||||
instance = new NullBean();
|
||||
}
|
||||
BeanWrapper bw = new BeanWrapperImpl(instance);
|
||||
initBeanWrapper(bw);
|
||||
return bw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a bean instance from the given supplier.
|
||||
* @param supplier the configured supplier
|
||||
* @param beanName the corresponding bean name
|
||||
* @param mbd the bean definition for the bean
|
||||
* @return the bean instance (possibly {@code null})
|
||||
* @since 6.0.7
|
||||
*/
|
||||
@Nullable
|
||||
protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd)
|
||||
throws Exception {
|
||||
|
||||
if (supplier instanceof ThrowingSupplier<?> throwingSupplier) {
|
||||
return throwingSupplier.getWithException();
|
||||
}
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
|
|
@ -40,6 +40,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jakarta.inject.Provider;
|
||||
|
|
@ -937,6 +938,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanName, RootBeanDefinition mbd)
|
||||
throws Exception {
|
||||
|
||||
if (supplier instanceof InstanceSupplier<?> instanceSupplier) {
|
||||
return instanceSupplier.get(RegisteredBean.of(this, beanName, mbd));
|
||||
}
|
||||
return super.obtainInstanceFromSupplier(supplier, beanName, mbd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInstantiateSingletons() throws BeansException {
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
|
|
@ -35,6 +35,7 @@ import org.springframework.util.function.ThrowingSupplier;
|
|||
* @since 6.0
|
||||
* @param <T> the type of instance supplied by this supplier
|
||||
* @see RegisteredBean
|
||||
* @see org.springframework.beans.factory.aot.BeanInstanceSupplier
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
|
||||
|
|
@ -74,19 +75,17 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
|
|||
*/
|
||||
default <V> InstanceSupplier<V> andThen(
|
||||
ThrowingBiFunction<RegisteredBean, ? super T, ? extends V> after) {
|
||||
|
||||
Assert.notNull(after, "'after' function must not be null");
|
||||
return new InstanceSupplier<>() {
|
||||
|
||||
@Override
|
||||
public V get(RegisteredBean registeredBean) throws Exception {
|
||||
return after.applyWithException(registeredBean, InstanceSupplier.this.get(registeredBean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getFactoryMethod() {
|
||||
return InstanceSupplier.this.getFactoryMethod();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -115,22 +114,21 @@ public interface InstanceSupplier<T> extends ThrowingSupplier<T> {
|
|||
*/
|
||||
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) {
|
||||
|
||||
if (supplier instanceof InstanceSupplier<T> instanceSupplier &&
|
||||
instanceSupplier.getFactoryMethod() == factoryMethod) {
|
||||
return instanceSupplier;
|
||||
}
|
||||
return new InstanceSupplier<>() {
|
||||
|
||||
return new InstanceSupplier<>() {
|
||||
@Override
|
||||
public T get(RegisteredBean registeredBean) throws Exception {
|
||||
return supplier.getWithException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getFactoryMethod() {
|
||||
return factoryMethod;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
|
|
@ -80,6 +80,18 @@ public final class RegisteredBean {
|
|||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RegisteredBean} instance for a regular bean.
|
||||
* @param beanFactory the source bean factory
|
||||
* @param beanName the bean name
|
||||
* @param mbd the pre-determined merged bean definition
|
||||
* @return a new {@link RegisteredBean} instance
|
||||
* @since 6.0.7
|
||||
*/
|
||||
static RegisteredBean of(ConfigurableListableBeanFactory beanFactory, String beanName, RootBeanDefinition mbd) {
|
||||
return new RegisteredBean(beanFactory, () -> beanName, false, () -> mbd, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RegisteredBean} instance for an inner-bean.
|
||||
* @param parent the parent of the inner-bean
|
||||
|
|
@ -220,45 +232,34 @@ public final class RegisteredBean {
|
|||
@Nullable
|
||||
private volatile String resolvedBeanName;
|
||||
|
||||
|
||||
InnerBeanResolver(RegisteredBean parent, @Nullable String innerBeanName,
|
||||
BeanDefinition innerBeanDefinition) {
|
||||
|
||||
Assert.isInstanceOf(AbstractAutowireCapableBeanFactory.class,
|
||||
parent.getBeanFactory());
|
||||
InnerBeanResolver(RegisteredBean parent, @Nullable String innerBeanName, BeanDefinition innerBeanDefinition) {
|
||||
Assert.isInstanceOf(AbstractAutowireCapableBeanFactory.class, parent.getBeanFactory());
|
||||
this.parent = parent;
|
||||
this.innerBeanName = innerBeanName;
|
||||
this.innerBeanDefinition = innerBeanDefinition;
|
||||
}
|
||||
|
||||
|
||||
String resolveBeanName() {
|
||||
String resolvedBeanName = this.resolvedBeanName;
|
||||
if (resolvedBeanName != null) {
|
||||
return resolvedBeanName;
|
||||
}
|
||||
resolvedBeanName = resolveInnerBean(
|
||||
(beanName, mergedBeanDefinition) -> beanName);
|
||||
resolvedBeanName = resolveInnerBean((beanName, mergedBeanDefinition) -> beanName);
|
||||
this.resolvedBeanName = resolvedBeanName;
|
||||
return resolvedBeanName;
|
||||
}
|
||||
|
||||
RootBeanDefinition resolveMergedBeanDefinition() {
|
||||
return resolveInnerBean(
|
||||
(beanName, mergedBeanDefinition) -> mergedBeanDefinition);
|
||||
return resolveInnerBean((beanName, mergedBeanDefinition) -> mergedBeanDefinition);
|
||||
}
|
||||
|
||||
private <T> T resolveInnerBean(
|
||||
BiFunction<String, RootBeanDefinition, T> resolver) {
|
||||
|
||||
private <T> T resolveInnerBean(BiFunction<String, RootBeanDefinition, T> resolver) {
|
||||
// Always use a fresh BeanDefinitionValueResolver in case the parent merged bean definition has changed.
|
||||
BeanDefinitionValueResolver beanDefinitionValueResolver = new BeanDefinitionValueResolver(
|
||||
(AbstractAutowireCapableBeanFactory) this.parent.getBeanFactory(),
|
||||
this.parent.getBeanName(), this.parent.getMergedBeanDefinition());
|
||||
return beanDefinitionValueResolver.resolveInnerBean(this.innerBeanName,
|
||||
this.innerBeanDefinition, resolver);
|
||||
return beanDefinitionValueResolver.resolveInnerBean(this.innerBeanName, this.innerBeanDefinition, resolver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
|
|
@ -27,10 +27,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link AbstractAutowireCapableBeanFactory} instance supplier
|
||||
* support.
|
||||
* Tests for {@link AbstractAutowireCapableBeanFactory} instance supplier support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class BeanFactorySupplierTests {
|
||||
|
||||
|
|
@ -44,13 +44,38 @@ public class BeanFactorySupplierTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void getBeanWhenUsingInstanceSupplier() {
|
||||
void getBeanWithInnerBeanUsingRegularSupplier() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition();
|
||||
beanDefinition.setInstanceSupplier(InstanceSupplier
|
||||
.of(registeredBean -> "I am bean " + registeredBean.getBeanName()));
|
||||
beanDefinition.setInstanceSupplier(() -> "I am supplied");
|
||||
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
|
||||
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
|
||||
beanFactory.registerBeanDefinition("test", outerBean);
|
||||
assertThat(beanFactory.getBean("test")).asString().startsWith("I am supplied");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeanWhenUsingInstanceSupplier() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
|
||||
beanDefinition.setInstanceSupplier(InstanceSupplier.of(registeredBean ->
|
||||
"I am bean " + registeredBean.getBeanName() + " of " + registeredBean.getBeanClass()));
|
||||
beanFactory.registerBeanDefinition("test", beanDefinition);
|
||||
assertThat(beanFactory.getBean("test")).isEqualTo("I am bean test");
|
||||
assertThat(beanFactory.getBean("test")).isEqualTo("I am bean test of class java.lang.String");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeanWithInnerBeanUsingInstanceSupplier() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(String.class);
|
||||
beanDefinition.setInstanceSupplier(InstanceSupplier.of(registeredBean ->
|
||||
"I am bean " + registeredBean.getBeanName() + " of " + registeredBean.getBeanClass()));
|
||||
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
|
||||
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
|
||||
beanFactory.registerBeanDefinition("test", outerBean);
|
||||
assertThat(beanFactory.getBean("test")).asString()
|
||||
.startsWith("I am bean (inner bean)")
|
||||
.endsWith(" of class java.lang.String");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -62,6 +87,17 @@ public class BeanFactorySupplierTests {
|
|||
assertThat(beanFactory.getBean("test")).isEqualTo("I am supplied");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeanWithInnerBeanUsingThrowableSupplier() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition();
|
||||
beanDefinition.setInstanceSupplier(ThrowingSupplier.of(() -> "I am supplied"));
|
||||
RootBeanDefinition outerBean = new RootBeanDefinition(String.class);
|
||||
outerBean.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition);
|
||||
beanFactory.registerBeanDefinition("test", outerBean);
|
||||
assertThat(beanFactory.getBean("test")).asString().startsWith("I am supplied");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeanWhenUsingThrowableSupplierThatThrowsCheckedException() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
|
|
|||
Loading…
Reference in New Issue