From 93a26514175c7b88537b6710e4559552ae484a41 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 10 Mar 2022 15:34:44 +0100 Subject: [PATCH] Make sure method injection handles ambiguous signatures This commit updates InjectionGenerator to request a resolved attribute with a dedicated type if multiple methods with the same name and the same number of arguments exist. This was previously done already for constructors and this commit harmonizes the algorithms to methods as well Closes gh-28154 --- .../beans/factory/generator/InjectionGenerator.java | 5 ++++- .../generator/BeanDefinitionsContributionTests.java | 2 +- .../factory/generator/InjectionGeneratorTests.java | 13 ++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/generator/InjectionGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/generator/InjectionGenerator.java index 13af095cc7..eb4f7cb8c1 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/generator/InjectionGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/generator/InjectionGenerator.java @@ -199,7 +199,10 @@ public class InjectionGenerator { code.add(")\n").indent().indent(); } attributesResolver.accept(code); - List parameters = resolveParameters(injectionPoint.getParameters(), false); + Parameter[] methodParameters = injectionPoint.getParameters(); + boolean isAmbiguous = Arrays.stream(injectionPoint.getDeclaringClass().getDeclaredMethods()) + .filter(method -> method.getName().equals(injectionPoint.getName()) && method.getParameterCount() == methodParameters.length).count() > 1; + List parameters = resolveParameters(methodParameters, isAmbiguous); code.add(" "); if (instantiation) { if (Modifier.isStatic(injectionPoint.getModifiers())) { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/generator/BeanDefinitionsContributionTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/generator/BeanDefinitionsContributionTests.java index 68fd627099..6ab9e57e37 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/generator/BeanDefinitionsContributionTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/generator/BeanDefinitionsContributionTests.java @@ -86,7 +86,7 @@ class BeanDefinitionsContributionTests { CodeSnippet code = contribute(beanFactory, createGenerationContext()); assertThat(code.getSnippet()).isEqualTo(""" BeanDefinitionRegistrar.of("counter", Integer.class).withFactoryMethod(Integer.class, "valueOf", int.class) - .instanceSupplier((instanceContext) -> instanceContext.create(beanFactory, (attributes) -> Integer.valueOf(attributes.get(0)))).customize((bd) -> bd.getConstructorArgumentValues().addIndexedArgumentValue(0, 42)).register(beanFactory); + .instanceSupplier((instanceContext) -> instanceContext.create(beanFactory, (attributes) -> Integer.valueOf(attributes.get(0, int.class)))).customize((bd) -> bd.getConstructorArgumentValues().addIndexedArgumentValue(0, 42)).register(beanFactory); BeanDefinitionRegistrar.of("name", String.class).withConstructor(String.class) .instanceSupplier((instanceContext) -> instanceContext.create(beanFactory, (attributes) -> new String(attributes.get(0, String.class)))).customize((bd) -> bd.getConstructorArgumentValues().addIndexedArgumentValue(0, "Hello")).register(beanFactory); """); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/generator/InjectionGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/generator/InjectionGeneratorTests.java index 708a3de995..2a8f667f7a 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/generator/InjectionGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/generator/InjectionGeneratorTests.java @@ -28,6 +28,7 @@ import org.springframework.aot.generator.ProtectedAccess; import org.springframework.aot.generator.ProtectedAccess.Options; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.generator.InjectionGeneratorTests.SimpleConstructorBean.InnerClass; +import org.springframework.beans.testfixture.beans.factory.generator.factory.SampleFactory; import org.springframework.javapoet.support.CodeSnippet; import org.springframework.util.ReflectionUtils; @@ -105,8 +106,14 @@ class InjectionGeneratorTests { @Test void generateInstantiationForMethodWithGenericParameters() { - assertThat(generateInstantiation(method(SampleBean.class, "source", ObjectProvider.class)).lines()).containsExactly( - "instanceContext.create(beanFactory, (attributes) -> beanFactory.getBean(InjectionGeneratorTests.SampleBean.class).source(attributes.get(0)))"); + assertThat(generateInstantiation(method(SampleBean.class, "sourceWithProvider", ObjectProvider.class)).lines()).containsExactly( + "instanceContext.create(beanFactory, (attributes) -> beanFactory.getBean(InjectionGeneratorTests.SampleBean.class).sourceWithProvider(attributes.get(0)))"); + } + + @Test + void generateInstantiationForAmbiguousMethod() { + assertThat(generateInstantiation(method(SampleFactory.class, "create", String.class)).lines()).containsExactly( + "instanceContext.create(beanFactory, (attributes) -> SampleFactory.create(attributes.get(0, String.class)))"); } @Test @@ -263,7 +270,7 @@ class InjectionGeneratorTests { return "source" + counter; } - String source(ObjectProvider counter) { + String sourceWithProvider(ObjectProvider counter) { return "source" + counter.getIfAvailable(() -> 0); }