Complete treatment of RuntimeBeanReference in BeanDefinitionValueResolver

See gh-35101
This commit is contained in:
Juergen Hoeller 2025-06-26 17:15:31 +02:00
parent f7fef93842
commit 4b44a34692
3 changed files with 34 additions and 16 deletions

View File

@ -107,6 +107,7 @@ public class RuntimeBeanReference implements BeanReference {
* @since 7.0
*/
public RuntimeBeanReference(String beanName, Class<?> beanType, boolean toParent) {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanType, "'beanType' must not be null");
this.beanName = beanName;
this.beanType = beanType;

View File

@ -333,6 +333,7 @@ public class BeanDefinitionValueResolver {
try {
Object bean;
Class<?> beanType = ref.getBeanType();
String resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
@ -342,21 +343,25 @@ public class BeanDefinitionValueResolver {
" in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
bean = (parent.containsBean(resolvedName) ?
parent.getBean(resolvedName, beanType) : parent.getBean(beanType));
}
else {
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
bean = parent.getBean(resolvedName);
}
}
else {
String resolvedName;
if (beanType != null) {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
if (this.beanFactory.containsBean(resolvedName)) {
bean = this.beanFactory.getBean(resolvedName, beanType);
}
else {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
}
}
else {
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
bean = this.beanFactory.getBean(resolvedName);
}
this.beanFactory.registerDependentBean(resolvedName, this.beanName);

View File

@ -555,21 +555,33 @@ class BeanFactoryUtilsTests {
}
@Test
void supportsMultipleTypesWithProperty() {
void supportsMultipleTypesWithPropertyAndSingleBean() {
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 rbd = new RootBeanDefinition(PropertyRecipient.class);
rbd.getPropertyValues().add("sfb", new RuntimeBeanReference(ITestBean.class));
lbf.registerBeanDefinition("recipient", rbd);
RootBeanDefinition rbd2 = new RootBeanDefinition(PropertyRecipient.class);
rbd2.getPropertyValues().add("sfb", new RuntimeBeanReference("sfb", ITestBean.class));
lbf.registerBeanDefinition("recipient2", rbd2);
assertThat(lbf.getBean("recipient", PropertyRecipient.class).sfb)
.isSameAs(lbf.getBean("sfb", ITestBean.class));
}
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));
@Test
void supportsMultipleTypesWithPropertyAndMultipleBeans() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
SupportsTypeSmartFactoryBean sfb = new SupportsTypeSmartFactoryBean();
lbf.registerSingleton("sfb", sfb);
SupportsTypeSmartFactoryBean other = new SupportsTypeSmartFactoryBean();
lbf.registerSingleton("other", other);
RootBeanDefinition rbd = new RootBeanDefinition(PropertyRecipient.class);
rbd.getPropertyValues().add("sfb", new RuntimeBeanReference("sfb", ITestBean.class));
lbf.registerBeanDefinition("recipient", rbd);
assertThat(lbf.getBean("recipient", PropertyRecipient.class).sfb)
.isSameAs(lbf.getBean("sfb", ITestBean.class));
}