Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Commit 74a0a66

Browse files
committed
Ignore target type when resolving factory method
Closes gh-1269
1 parent eba6bc4 commit 74a0a66

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

spring-aot/src/main/java/org/springframework/aot/context/bootstrap/generator/bean/descriptor/BeanInstanceExecutableSupplier.java

+19-7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
4242
import org.springframework.beans.factory.config.ConstructorArgumentValues;
4343
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
44+
import org.springframework.beans.factory.support.AbstractBeanDefinition;
4445
import org.springframework.beans.factory.support.RootBeanDefinition;
4546
import org.springframework.core.ResolvableType;
4647
import org.springframework.core.annotation.MergedAnnotations;
@@ -69,7 +70,7 @@ Executable detectBeanInstanceExecutable(BeanDefinition beanDefinition) {
6970
Supplier<ResolvableType> beanType = () -> getBeanType(beanDefinition);
7071
List<ResolvableType> valueTypes = beanDefinition.hasConstructorArgumentValues()
7172
? determineParameterValueTypes(beanDefinition.getConstructorArgumentValues()) : Collections.emptyList();
72-
Method resolvedFactoryMethod = resolveFactoryMethod(beanDefinition, beanType, valueTypes);
73+
Method resolvedFactoryMethod = resolveFactoryMethod(beanDefinition, valueTypes);
7374
if (resolvedFactoryMethod != null) {
7475
return resolvedFactoryMethod;
7576
}
@@ -129,8 +130,7 @@ private ResolvableType extractTypeFromBeanDefinition(ResolvableType type) {
129130
return type;
130131
}
131132

132-
private Method resolveFactoryMethod(BeanDefinition beanDefinition, Supplier<ResolvableType> beanType,
133-
List<ResolvableType> valueTypes) {
133+
private Method resolveFactoryMethod(BeanDefinition beanDefinition, List<ResolvableType> valueTypes) {
134134
if (beanDefinition instanceof RootBeanDefinition) {
135135
RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinition;
136136
Method resolvedFactoryMethod = rootBeanDefinition.getResolvedFactoryMethod();
@@ -141,8 +141,12 @@ private Method resolveFactoryMethod(BeanDefinition beanDefinition, Supplier<Reso
141141
String factoryMethodName = beanDefinition.getFactoryMethodName();
142142
if (factoryMethodName != null) {
143143
List<Method> methods = new ArrayList<>();
144-
ReflectionUtils.doWithMethods(beanType.get().toClass(), methods::add,
145-
(method) -> isFactoryMethodCandidate(beanDefinition, method, factoryMethodName));
144+
Class<?> beanClass = getBeanClass(beanDefinition);
145+
if (beanClass == null) {
146+
throw new IllegalStateException("Failed to determine bean class of " + beanDefinition);
147+
}
148+
ReflectionUtils.doWithMethods(beanClass, methods::add,
149+
(method) -> isFactoryMethodCandidate(beanClass, method, factoryMethodName));
146150
if (methods.size() >= 1) {
147151
Function<Method, List<ResolvableType>> parameterTypesFactory = (method) -> {
148152
List<ResolvableType> types = new ArrayList<>();
@@ -157,10 +161,10 @@ private Method resolveFactoryMethod(BeanDefinition beanDefinition, Supplier<Reso
157161
return null;
158162
}
159163

160-
private boolean isFactoryMethodCandidate(BeanDefinition beanDefinition, Method method, String factoryMethodName) {
164+
private boolean isFactoryMethodCandidate(Class<?> beanClass, Method method, String factoryMethodName) {
161165
if (method.getName().equals(factoryMethodName)) {
162166
if (Modifier.isStatic(method.getModifiers())) {
163-
return method.getDeclaringClass().equals(getBeanType(beanDefinition).toClass());
167+
return method.getDeclaringClass().equals(beanClass);
164168
}
165169
return !Modifier.isPrivate(method.getModifiers());
166170
}
@@ -314,6 +318,14 @@ private Class<?> getFactoryBeanClass(BeanDefinition beanDefinition) {
314318
return null;
315319
}
316320

321+
private Class<?> getBeanClass(BeanDefinition beanDefinition) {
322+
if (beanDefinition instanceof AbstractBeanDefinition) {
323+
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDefinition;
324+
return abd.hasBeanClass() ? abd.getBeanClass() : loadClass(abd.getBeanClassName());
325+
}
326+
return (beanDefinition.getBeanClassName() != null) ? loadClass(beanDefinition.getBeanClassName()) : null;
327+
}
328+
317329
private ResolvableType getBeanType(BeanDefinition beanDefinition) {
318330
ResolvableType resolvableType = beanDefinition.getResolvableType();
319331
if (resolvableType != ResolvableType.NONE) {

spring-aot/src/test/java/org/springframework/aot/context/bootstrap/generator/bean/descriptor/BeanInstanceExecutableSupplierTests.java

+25-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,17 @@
4646
class BeanInstanceExecutableSupplierTests {
4747

4848
@Test
49-
void detectBeanInstanceExecutableWithFactoryMethodName() {
49+
void detectBeanInstanceExecutableWithBeanClassAndFactoryMethodName() {
50+
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
51+
beanFactory.registerSingleton("testBean", "test");
52+
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleFactory.class)
53+
.setFactoryMethod("create").addConstructorArgReference("testBean").getBeanDefinition();
54+
Executable executable = detectBeanInstanceExecutable(beanFactory, beanDefinition);
55+
assertThat(executable).isNotNull().isEqualTo(ReflectionUtils.findMethod(SampleFactory.class, "create", String.class));
56+
}
57+
58+
@Test
59+
void detectBeanInstanceExecutableWithBeanClassNameAndFactoryMethodName() {
5060
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
5161
beanFactory.registerSingleton("testBean", "test");
5262
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleFactory.class.getName())
@@ -60,7 +70,7 @@ void beanDefinitionWithFactoryMethodNameAndAssignableConstructorArg() {
6070
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
6171
beanFactory.registerSingleton("testNumber", 1L);
6272
beanFactory.registerSingleton("testBean", "test");
63-
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleFactory.class.getName())
73+
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleFactory.class)
6474
.setFactoryMethod("create").addConstructorArgReference("testNumber")
6575
.addConstructorArgReference("testBean").getBeanDefinition();
6676
Executable executable = detectBeanInstanceExecutable(beanFactory, beanDefinition);
@@ -76,12 +86,23 @@ void beanDefinitionWithFactoryMethodNameAndMatchingMethodNamesThatShouldBeIgnore
7686
assertThat(executable).isNotNull().isEqualTo(ReflectionUtils.findMethod(DummySampleFactory.class, "of", Integer.class));
7787
}
7888

89+
@Test
90+
void detectBeanInstanceExecutableWithBeanClassAndFactoryMethodNameIgnoreTargetType() {
91+
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
92+
beanFactory.registerSingleton("testBean", "test");
93+
RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition(SampleFactory.class)
94+
.setFactoryMethod("create").addConstructorArgReference("testBean").getBeanDefinition();
95+
beanDefinition.setTargetType(String.class);
96+
Executable executable = detectBeanInstanceExecutable(beanFactory, beanDefinition);
97+
assertThat(executable).isNotNull().isEqualTo(ReflectionUtils.findMethod(SampleFactory.class, "create", String.class));
98+
}
99+
79100
@Test
80101
void beanDefinitionWithConstructorArgsForMultipleConstructors() throws Exception {
81102
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
82103
beanFactory.registerSingleton("testNumber", 1L);
83104
beanFactory.registerSingleton("testBean", "test");
84-
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleBeanWithConstructors.class.getName())
105+
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(SampleBeanWithConstructors.class)
85106
.addConstructorArgReference("testNumber")
86107
.addConstructorArgReference("testBean").getBeanDefinition();
87108
Executable executable = detectBeanInstanceExecutable(beanFactory, beanDefinition);
@@ -93,7 +114,7 @@ void genericBeanDefinitionWithConstructorArgsForMultipleConstructors() throws Ex
93114
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
94115
beanFactory.registerSingleton("testNumber", 1L);
95116
beanFactory.registerSingleton("testBean", "test");
96-
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SampleBeanWithConstructors.class.getName())
117+
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SampleBeanWithConstructors.class)
97118
.addConstructorArgReference("testNumber")
98119
.addConstructorArgReference("testBean").getBeanDefinition();
99120
Executable executable = detectBeanInstanceExecutable(beanFactory, beanDefinition);

0 commit comments

Comments
 (0)