From cba2b6eaf440b61895d2eea1e008eefe393dc5b3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 3 Aug 2023 18:10:07 +0200 Subject: [PATCH] Check FactoryBean targetType for generic type as well Closes gh-30987 --- .../AbstractAutowireCapableBeanFactory.java | 5 ++++ .../DefaultListableBeanFactoryTests.java | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 8f03d2f605a1..667969ed83d7 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -908,6 +908,11 @@ protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefiniti // static factory method signature or from class inheritance hierarchy... return getTypeForFactoryBeanFromMethod(mbd.getBeanClass(), factoryMethodName); } + + result = getFactoryBeanGeneric(mbd.targetType); + if (result.resolve() != null) { + return result; + } result = getFactoryBeanGeneric(beanType); if (result.resolve() != null) { return result; 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 76962198046f..98f69c44d402 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 @@ -1980,6 +1980,16 @@ void getBeanNamesForTypeWithPrototypeScopedFactoryBean() { assertBeanNamesForType(FactoryBean.class, false, false); } + @Test // gh-30987 + void getBeanNamesForTypeWithFactoryBeanDefinedAsTargetType() { + RootBeanDefinition beanDefinition = new RootBeanDefinition(TestRepositoryFactoryBean.class); + beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(TestRepositoryFactoryBean.class, + CityRepository.class, Object.class, Object.class)); + lbf.registerBeanDefinition("factoryBean", beanDefinition); + assertBeanNamesForType(TestRepositoryFactoryBean.class, true, false, "&factoryBean"); + assertBeanNamesForType(CityRepository.class, true, false, "factoryBean"); + } + /** * Verifies that a dependency on a {@link FactoryBean} can not * be autowired by name, as & is an illegal character in @@ -3068,6 +3078,25 @@ public T call() { } + public static class TestRepositoryFactoryBean, S, ID extends Serializable> + extends RepositoryFactoryBeanSupport { + + @Override + public T getObject() throws Exception { + throw new IllegalArgumentException("Should not be called"); + } + + @Override + public Class getObjectType() { + throw new IllegalArgumentException("Should not be called"); + } + } + + public record City(String name) {} + + public static class CityRepository implements Repository {} + + public static class LazyInitFactory implements FactoryBean { public boolean initialized = false;