diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 3ce177368d8..83f3cb00472 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -639,10 +639,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } else { - if (includeNonSingletons || isNonLazyDecorated || - (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) { + if (includeNonSingletons || isNonLazyDecorated) { 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) { // In case of FactoryBean, try to match FactoryBean instance itself next. beanName = FACTORY_BEAN_PREFIX + beanName; diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 3216b92938d..b11449d0312 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/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(); } + @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 void initializedFactoryBeanFoundByNonEagerTypeMatching() { Properties p = new Properties();