Skip to content

Commit c5da405

Browse files
committed
Consistent type-based bean lookup for RuntimeBeanReference
See gh-35101
1 parent 06ef82e commit c5da405

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/config/RuntimeBeanReference.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,32 @@ public RuntimeBeanReference(Class<?> beanType, boolean toParent) {
8787
this.toParent = toParent;
8888
}
8989

90+
/**
91+
* Create a new RuntimeBeanReference to a bean of the given type.
92+
* @param beanName name of the target bean
93+
* @param beanType type of the target bean
94+
* @since 7.0
95+
*/
96+
public RuntimeBeanReference(String beanName, Class<?> beanType) {
97+
this(beanName, beanType, false);
98+
}
99+
100+
/**
101+
* Create a new RuntimeBeanReference to a bean of the given type,
102+
* with the option to mark it as reference to a bean in the parent factory.
103+
* @param beanName name of the target bean
104+
* @param beanType type of the target bean
105+
* @param toParent whether this is an explicit reference to a bean in the
106+
* parent factory
107+
* @since 7.0
108+
*/
109+
public RuntimeBeanReference(String beanName, Class<?> beanType, boolean toParent) {
110+
Assert.notNull(beanType, "'beanType' must not be null");
111+
this.beanName = beanName;
112+
this.beanType = beanType;
113+
this.toParent = toParent;
114+
}
115+
90116

91117
/**
92118
* Return the requested bean name, or the fully-qualified type name

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ else if (candidateNames.length > 1) {
15881588
private <T> @Nullable NamedBeanHolder<T> resolveNamedBean(
15891589
String beanName, ResolvableType requiredType, @Nullable Object @Nullable [] args) throws BeansException {
15901590

1591-
Object bean = getBean(beanName, null, args);
1591+
Object bean = (args != null ? getBean(beanName, args) : resolveBean(beanName, requiredType));
15921592
if (bean instanceof NullBean) {
15931593
return null;
15941594
}

spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.junit.jupiter.api.BeforeEach;
2727
import org.junit.jupiter.api.Test;
2828

29+
import org.springframework.beans.factory.config.RuntimeBeanReference;
2930
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3031
import org.springframework.beans.factory.support.RootBeanDefinition;
3132
import org.springframework.beans.factory.support.StaticListableBeanFactory;
@@ -465,9 +466,9 @@ void supportsMultipleTypesWithDefaultFactory() {
465466
lbf.registerSingleton("sfb1", sfb1);
466467
lbf.registerSingleton("sfb2", sfb2);
467468
lbf.registerBeanDefinition("recipient",
468-
new RootBeanDefinition(Recipient.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
469+
new RootBeanDefinition(ConstructorRecipient.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
469470

470-
Recipient recipient = lbf.getBean("recipient", Recipient.class);
471+
ConstructorRecipient recipient = lbf.getBean("recipient", ConstructorRecipient.class);
471472
assertThat(recipient.sfb1).isSameAs(lbf.getBean("sfb1", TestBean.class));
472473
assertThat(recipient.sfb2).isSameAs(lbf.getBean("sfb2", TestBean.class));
473474

@@ -553,6 +554,24 @@ void testSupportsMultipleTypes(ListableBeanFactory lbf) {
553554
assertThat(lbf.getBean("sfb2")).isInstanceOf(String.class);
554555
}
555556

557+
@Test
558+
void supportsMultipleTypesWithProperty() {
559+
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
560+
SupportsTypeSmartFactoryBean sfb = new SupportsTypeSmartFactoryBean();
561+
lbf.registerSingleton("sfb", sfb);
562+
563+
RootBeanDefinition rbd1 = new RootBeanDefinition(PropertyRecipient.class);
564+
rbd1.getPropertyValues().add("sfb", new RuntimeBeanReference(ITestBean.class));
565+
lbf.registerBeanDefinition("recipient1", rbd1);
566+
567+
RootBeanDefinition rbd2 = new RootBeanDefinition(PropertyRecipient.class);
568+
rbd2.getPropertyValues().add("sfb", new RuntimeBeanReference("sfb", ITestBean.class));
569+
lbf.registerBeanDefinition("recipient2", rbd2);
570+
571+
assertThat(lbf.getBean("recipient1", PropertyRecipient.class).sfb).isSameAs(lbf.getBean("sfb", ITestBean.class));
572+
assertThat(lbf.getBean("recipient2", PropertyRecipient.class).sfb).isSameAs(lbf.getBean("sfb", ITestBean.class));
573+
}
574+
556575

557576
@Retention(RetentionPolicy.RUNTIME)
558577
@interface ControllerAdvice {
@@ -650,9 +669,10 @@ public boolean supportsType(Class<?> type) {
650669
}
651670

652671

653-
static class Recipient {
672+
static class ConstructorRecipient {
654673

655-
public Recipient(ITestBean sfb1, ITestBean sfb2, List<ITestBean> testBeanList, List<CharSequence> stringList,
674+
public ConstructorRecipient(ITestBean sfb1, ITestBean sfb2,
675+
List<ITestBean> testBeanList, List<CharSequence> stringList,
656676
ObjectProvider<ITestBean> testBeanProvider, ObjectProvider<CharSequence> stringProvider) {
657677
this.sfb1 = sfb1;
658678
this.sfb2 = sfb2;
@@ -675,4 +695,14 @@ public Recipient(ITestBean sfb1, ITestBean sfb2, List<ITestBean> testBeanList, L
675695
ObjectProvider<CharSequence> stringProvider;
676696
}
677697

698+
699+
static class PropertyRecipient {
700+
701+
ITestBean sfb;
702+
703+
public void setSfb(ITestBean sfb) {
704+
this.sfb = sfb;
705+
}
706+
}
707+
678708
}

0 commit comments

Comments
 (0)