diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java index ab98f89439a..a160d986f89 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java @@ -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 extends AutowiredElementResolver impl private BeanInstanceSupplier(ExecutableLookup lookup, @Nullable ThrowingBiFunction 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 extends AutowiredElementResolver impl * @param parameterTypes the constructor parameter types * @return a new {@link BeanInstanceSupplier} instance */ - public static BeanInstanceSupplier forConstructor( - Class... parameterTypes) { - + public static BeanInstanceSupplier 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 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 withGenerator( ThrowingBiFunction 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 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 withGenerator( - ThrowingFunction generator) { + public BeanInstanceSupplier withGenerator(ThrowingFunction 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 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 withGenerator(ThrowingSupplier generator) { Assert.notNull(generator, "'generator' must not be null"); @@ -282,8 +278,7 @@ public final class BeanInstanceSupplier 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 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 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 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 { - if (executable instanceof Constructor constructor) { - return (T) instantiate(constructor, arguments); + private T instantiate(ConfigurableBeanFactory beanFactory, Executable executable, Object[] args) { + if (executable instanceof Constructor constructor) { + try { + return (T) instantiate(constructor, args); } - if (executable instanceof Method method) { - return (T) instantiate(beanFactory, method, arguments); + catch (Exception ex) { + throw new BeanInstantiationException(constructor, ex.getMessage(), ex); } } - catch (Exception ex) { - throw new BeanCreationException( - "Unable to instantiate bean using " + executable, ex); + 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()); + 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 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 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 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 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 extends AutowiredElementResolver impl this.methodName, toCommaSeparatedNames(this.parameterTypes), this.declaringClass); } - } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 7c17284a442..abf24370f45 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -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(); } /** diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 5c8cea79336..14cad2960be 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -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()) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/InstanceSupplier.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/InstanceSupplier.java index eddbc795472..8d930b35739 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/InstanceSupplier.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/InstanceSupplier.java @@ -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 the type of instance supplied by this supplier * @see RegisteredBean + * @see org.springframework.beans.factory.aot.BeanInstanceSupplier */ @FunctionalInterface public interface InstanceSupplier extends ThrowingSupplier { @@ -74,19 +75,17 @@ public interface InstanceSupplier extends ThrowingSupplier { */ default InstanceSupplier andThen( ThrowingBiFunction 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 extends ThrowingSupplier { */ static InstanceSupplier using(@Nullable Method factoryMethod, ThrowingSupplier supplier) { Assert.notNull(supplier, "Supplier must not be null"); - if (supplier instanceof InstanceSupplier instanceSupplier - && instanceSupplier.getFactoryMethod() == factoryMethod) { + + if (supplier instanceof InstanceSupplier 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; } - }; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java index 06a17bd563c..c8c5487153c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java @@ -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 resolveInnerBean( - BiFunction resolver) { - + private T resolveInnerBean(BiFunction 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); } - } } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactorySupplierTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactorySupplierTests.java index d07cd08abda..d147b24d350 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactorySupplierTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactorySupplierTests.java @@ -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();