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
This commit is contained in:
Stephane Nicoll 2022-03-10 15:34:44 +01:00
parent f3181dc583
commit 93a2651417
3 changed files with 15 additions and 5 deletions

View File

@ -199,7 +199,10 @@ public class InjectionGenerator {
code.add(")\n").indent().indent(); code.add(")\n").indent().indent();
} }
attributesResolver.accept(code); attributesResolver.accept(code);
List<CodeBlock> 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<CodeBlock> parameters = resolveParameters(methodParameters, isAmbiguous);
code.add(" "); code.add(" ");
if (instantiation) { if (instantiation) {
if (Modifier.isStatic(injectionPoint.getModifiers())) { if (Modifier.isStatic(injectionPoint.getModifiers())) {

View File

@ -86,7 +86,7 @@ class BeanDefinitionsContributionTests {
CodeSnippet code = contribute(beanFactory, createGenerationContext()); CodeSnippet code = contribute(beanFactory, createGenerationContext());
assertThat(code.getSnippet()).isEqualTo(""" assertThat(code.getSnippet()).isEqualTo("""
BeanDefinitionRegistrar.of("counter", Integer.class).withFactoryMethod(Integer.class, "valueOf", int.class) 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) 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); .instanceSupplier((instanceContext) -> instanceContext.create(beanFactory, (attributes) -> new String(attributes.get(0, String.class)))).customize((bd) -> bd.getConstructorArgumentValues().addIndexedArgumentValue(0, "Hello")).register(beanFactory);
"""); """);

View File

@ -28,6 +28,7 @@ import org.springframework.aot.generator.ProtectedAccess;
import org.springframework.aot.generator.ProtectedAccess.Options; import org.springframework.aot.generator.ProtectedAccess.Options;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.generator.InjectionGeneratorTests.SimpleConstructorBean.InnerClass; 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.javapoet.support.CodeSnippet;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
@ -105,8 +106,14 @@ class InjectionGeneratorTests {
@Test @Test
void generateInstantiationForMethodWithGenericParameters() { void generateInstantiationForMethodWithGenericParameters() {
assertThat(generateInstantiation(method(SampleBean.class, "source", ObjectProvider.class)).lines()).containsExactly( assertThat(generateInstantiation(method(SampleBean.class, "sourceWithProvider", ObjectProvider.class)).lines()).containsExactly(
"instanceContext.create(beanFactory, (attributes) -> beanFactory.getBean(InjectionGeneratorTests.SampleBean.class).source(attributes.get(0)))"); "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 @Test
@ -263,7 +270,7 @@ class InjectionGeneratorTests {
return "source" + counter; return "source" + counter;
} }
String source(ObjectProvider<Integer> counter) { String sourceWithProvider(ObjectProvider<Integer> counter) {
return "source" + counter.getIfAvailable(() -> 0); return "source" + counter.getIfAvailable(() -> 0);
} }