Browse Source

Perform type check before singleton check for early FactoryBean matching

Closes gh-34710
pull/34732/head
Juergen Hoeller 9 months ago
parent
commit
e7db15b325
  1. 9
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  2. 26
      spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

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

@ -639,10 +639,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
} }
else { else {
if (includeNonSingletons || isNonLazyDecorated || if (includeNonSingletons || isNonLazyDecorated) {
(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
} }
else if (allowFactoryBeanInit) {
// Type check before singleton check, avoiding FactoryBean instantiation
// for early FactoryBean.isSingleton() calls on non-matching beans.
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit) &&
isSingleton(beanName, mbd, dbd);
}
if (!matchFound) { if (!matchFound) {
// In case of FactoryBean, try to match FactoryBean instance itself next. // In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName; beanName = FACTORY_BEAN_PREFIX + beanName;

26
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

@ -263,6 +263,32 @@ class DefaultListableBeanFactoryTests {
assertThat(DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isFalse(); assertThat(DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isFalse();
} }
@Test
void nonInitializedFactoryBeanIgnoredByEagerTypeMatching() {
RootBeanDefinition bd = new RootBeanDefinition(DummyFactory.class);
bd.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, String.class);
lbf.registerBeanDefinition("x1", bd);
assertBeanNamesForType(TestBean.class, false, true);
assertThat(lbf.getBeanNamesForAnnotation(SuppressWarnings.class)).isEmpty();
assertThat(lbf.containsSingleton("x1")).isFalse();
assertThat(lbf.containsBean("x1")).isTrue();
assertThat(lbf.containsBean("&x1")).isTrue();
assertThat(lbf.isSingleton("x1")).isTrue();
assertThat(lbf.isSingleton("&x1")).isTrue();
assertThat(lbf.isPrototype("x1")).isFalse();
assertThat(lbf.isPrototype("&x1")).isFalse();
assertThat(lbf.isTypeMatch("x1", TestBean.class)).isTrue();
assertThat(lbf.isTypeMatch("&x1", TestBean.class)).isFalse();
assertThat(lbf.isTypeMatch("&x1", DummyFactory.class)).isTrue();
assertThat(lbf.isTypeMatch("&x1", ResolvableType.forClass(DummyFactory.class))).isTrue();
assertThat(lbf.isTypeMatch("&x1", ResolvableType.forClassWithGenerics(FactoryBean.class, Object.class))).isTrue();
assertThat(lbf.isTypeMatch("&x1", ResolvableType.forClassWithGenerics(FactoryBean.class, String.class))).isFalse();
assertThat(lbf.getType("x1")).isEqualTo(TestBean.class);
assertThat(lbf.getType("&x1")).isEqualTo(DummyFactory.class);
}
@Test @Test
void initializedFactoryBeanFoundByNonEagerTypeMatching() { void initializedFactoryBeanFoundByNonEagerTypeMatching() {
Properties p = new Properties(); Properties p = new Properties();

Loading…
Cancel
Save