Consistent type-based bean lookup for RuntimeBeanReference
See gh-35101
This commit is contained in:
parent
06ef82e9a5
commit
c5da405314
|
@ -87,6 +87,32 @@ public class RuntimeBeanReference implements BeanReference {
|
|||
this.toParent = toParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to a bean of the given type.
|
||||
* @param beanName name of the target bean
|
||||
* @param beanType type of the target bean
|
||||
* @since 7.0
|
||||
*/
|
||||
public RuntimeBeanReference(String beanName, Class<?> beanType) {
|
||||
this(beanName, beanType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to a bean of the given type,
|
||||
* with the option to mark it as reference to a bean in the parent factory.
|
||||
* @param beanName name of the target bean
|
||||
* @param beanType type of the target bean
|
||||
* @param toParent whether this is an explicit reference to a bean in the
|
||||
* parent factory
|
||||
* @since 7.0
|
||||
*/
|
||||
public RuntimeBeanReference(String beanName, Class<?> beanType, boolean toParent) {
|
||||
Assert.notNull(beanType, "'beanType' must not be null");
|
||||
this.beanName = beanName;
|
||||
this.beanType = beanType;
|
||||
this.toParent = toParent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the requested bean name, or the fully-qualified type name
|
||||
|
|
|
@ -1588,7 +1588,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
private <T> @Nullable NamedBeanHolder<T> resolveNamedBean(
|
||||
String beanName, ResolvableType requiredType, @Nullable Object @Nullable [] args) throws BeansException {
|
||||
|
||||
Object bean = getBean(beanName, null, args);
|
||||
Object bean = (args != null ? getBean(beanName, args) : resolveBean(beanName, requiredType));
|
||||
if (bean instanceof NullBean) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.jspecify.annotations.Nullable;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
|
@ -465,9 +466,9 @@ class BeanFactoryUtilsTests {
|
|||
lbf.registerSingleton("sfb1", sfb1);
|
||||
lbf.registerSingleton("sfb2", sfb2);
|
||||
lbf.registerBeanDefinition("recipient",
|
||||
new RootBeanDefinition(Recipient.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
new RootBeanDefinition(ConstructorRecipient.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
Recipient recipient = lbf.getBean("recipient", Recipient.class);
|
||||
ConstructorRecipient recipient = lbf.getBean("recipient", ConstructorRecipient.class);
|
||||
assertThat(recipient.sfb1).isSameAs(lbf.getBean("sfb1", TestBean.class));
|
||||
assertThat(recipient.sfb2).isSameAs(lbf.getBean("sfb2", TestBean.class));
|
||||
|
||||
|
@ -553,6 +554,24 @@ class BeanFactoryUtilsTests {
|
|||
assertThat(lbf.getBean("sfb2")).isInstanceOf(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportsMultipleTypesWithProperty() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
SupportsTypeSmartFactoryBean sfb = new SupportsTypeSmartFactoryBean();
|
||||
lbf.registerSingleton("sfb", sfb);
|
||||
|
||||
RootBeanDefinition rbd1 = new RootBeanDefinition(PropertyRecipient.class);
|
||||
rbd1.getPropertyValues().add("sfb", new RuntimeBeanReference(ITestBean.class));
|
||||
lbf.registerBeanDefinition("recipient1", rbd1);
|
||||
|
||||
RootBeanDefinition rbd2 = new RootBeanDefinition(PropertyRecipient.class);
|
||||
rbd2.getPropertyValues().add("sfb", new RuntimeBeanReference("sfb", ITestBean.class));
|
||||
lbf.registerBeanDefinition("recipient2", rbd2);
|
||||
|
||||
assertThat(lbf.getBean("recipient1", PropertyRecipient.class).sfb).isSameAs(lbf.getBean("sfb", ITestBean.class));
|
||||
assertThat(lbf.getBean("recipient2", PropertyRecipient.class).sfb).isSameAs(lbf.getBean("sfb", ITestBean.class));
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ControllerAdvice {
|
||||
|
@ -650,9 +669,10 @@ class BeanFactoryUtilsTests {
|
|||
}
|
||||
|
||||
|
||||
static class Recipient {
|
||||
static class ConstructorRecipient {
|
||||
|
||||
public Recipient(ITestBean sfb1, ITestBean sfb2, List<ITestBean> testBeanList, List<CharSequence> stringList,
|
||||
public ConstructorRecipient(ITestBean sfb1, ITestBean sfb2,
|
||||
List<ITestBean> testBeanList, List<CharSequence> stringList,
|
||||
ObjectProvider<ITestBean> testBeanProvider, ObjectProvider<CharSequence> stringProvider) {
|
||||
this.sfb1 = sfb1;
|
||||
this.sfb2 = sfb2;
|
||||
|
@ -675,4 +695,14 @@ class BeanFactoryUtilsTests {
|
|||
ObjectProvider<CharSequence> stringProvider;
|
||||
}
|
||||
|
||||
|
||||
static class PropertyRecipient {
|
||||
|
||||
ITestBean sfb;
|
||||
|
||||
public void setSfb(ITestBean sfb) {
|
||||
this.sfb = sfb;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue