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;
|
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
|
* 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(
|
private <T> @Nullable NamedBeanHolder<T> resolveNamedBean(
|
||||||
String beanName, ResolvableType requiredType, @Nullable Object @Nullable [] args) throws BeansException {
|
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) {
|
if (bean instanceof NullBean) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.jspecify.annotations.Nullable;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
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.DefaultListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||||
|
@ -465,9 +466,9 @@ class BeanFactoryUtilsTests {
|
||||||
lbf.registerSingleton("sfb1", sfb1);
|
lbf.registerSingleton("sfb1", sfb1);
|
||||||
lbf.registerSingleton("sfb2", sfb2);
|
lbf.registerSingleton("sfb2", sfb2);
|
||||||
lbf.registerBeanDefinition("recipient",
|
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.sfb1).isSameAs(lbf.getBean("sfb1", TestBean.class));
|
||||||
assertThat(recipient.sfb2).isSameAs(lbf.getBean("sfb2", TestBean.class));
|
assertThat(recipient.sfb2).isSameAs(lbf.getBean("sfb2", TestBean.class));
|
||||||
|
|
||||||
|
@ -553,6 +554,24 @@ class BeanFactoryUtilsTests {
|
||||||
assertThat(lbf.getBean("sfb2")).isInstanceOf(String.class);
|
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)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface ControllerAdvice {
|
@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) {
|
ObjectProvider<ITestBean> testBeanProvider, ObjectProvider<CharSequence> stringProvider) {
|
||||||
this.sfb1 = sfb1;
|
this.sfb1 = sfb1;
|
||||||
this.sfb2 = sfb2;
|
this.sfb2 = sfb2;
|
||||||
|
@ -675,4 +695,14 @@ class BeanFactoryUtilsTests {
|
||||||
ObjectProvider<CharSequence> stringProvider;
|
ObjectProvider<CharSequence> stringProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class PropertyRecipient {
|
||||||
|
|
||||||
|
ITestBean sfb;
|
||||||
|
|
||||||
|
public void setSfb(ITestBean sfb) {
|
||||||
|
this.sfb = sfb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue