From 912593470d7ccc3a1dcae8d91fc8a5329470163e Mon Sep 17 00:00:00 2001 From: Romain Quinio Date: Mon, 13 Mar 2023 21:33:34 +0100 Subject: [PATCH] Support SpringDI List injection with @Inject Spring has support for JSR-303 annotations, so features of @Autowired are also applicable to @Inject fields/methods. Also mention the @All qualifier in the conversion table of the userguide. --- docs/src/main/asciidoc/spring-di.adoc | 2 +- .../di/deployment/SpringDIProcessor.java | 52 ++++++++++++------- .../spring/di/deployment/ListOfBeansTest.java | 25 ++++++++- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/docs/src/main/asciidoc/spring-di.adoc b/docs/src/main/asciidoc/spring-di.adoc index 7a2bc51c96a6e..5c7f0386a113f 100644 --- a/docs/src/main/asciidoc/spring-di.adoc +++ b/docs/src/main/asciidoc/spring-di.adoc @@ -283,7 +283,7 @@ The following table shows how Spring DI annotations can be converted to CDI and |@Autowired |@Inject -| +|If the type is `java.util.List`, the `io.quarkus.arc.All` qualifier is added. |@Qualifier |@Named diff --git a/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java b/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java index 9126aa2f04941..093258af3d796 100644 --- a/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java +++ b/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java @@ -395,14 +395,10 @@ Set getAnnotationsToAdd( Collections.singletonList((AnnotationValue.createStringValue("value", value))))); } } - - // in Spring List means that all instances of SomeBean should be injected - if (fieldInfo.type().name().equals(DotNames.LIST)) { - annotationsToAdd.add(create( - QUARKUS_ALL_ANNOTATION, - target, - Collections.emptyList())); - } + addAllAnnotationOnListField(target, annotationsToAdd, fieldInfo); + } else if (fieldInfo.hasAnnotation(CDI_INJECT_ANNOTATION)) { + // Mix case of JSR-303 support in Spring + addAllAnnotationOnListField(target, annotationsToAdd, fieldInfo); } else if (fieldInfo.hasAnnotation(SPRING_VALUE_ANNOTATION)) { final AnnotationInstance annotation = fieldInfo.annotation(SPRING_VALUE_ANNOTATION); addSpringValueAnnotations(target, annotation, true, annotationsToAdd); @@ -437,18 +433,11 @@ Set getAnnotationsToAdd( CDI_INJECT_ANNOTATION, target, Collections.emptyList())); - // in Spring List means that all instances of SomeBean should be injected - List parameters = methodInfo.parameterTypes(); - for (int i = 0; i < parameters.size(); i++) { - Type parameter = parameters.get(i); - if (parameter.name().equals(DotNames.LIST)) { - annotationsToAdd.add(create( - QUARKUS_ALL_ANNOTATION, - MethodParameterInfo.create(methodInfo, (short) i), - Collections.emptyList())); - } - } + addAllAnnotationOnMethodListParameters(annotationsToAdd, methodInfo); + } else if (methodInfo.hasAnnotation(CDI_INJECT_ANNOTATION)) { + // Mix case of JSR-303 support in Spring + addAllAnnotationOnMethodListParameters(annotationsToAdd, methodInfo); } // add method parameter conversion annotations @@ -473,6 +462,31 @@ Set getAnnotationsToAdd( return annotationsToAdd; } + private void addAllAnnotationOnListField(AnnotationTarget target, Set annotationsToAdd, + FieldInfo fieldInfo) { + // in Spring List means that all instances of SomeBean should be injected + if (fieldInfo.type().name().equals(DotNames.LIST)) { + annotationsToAdd.add(create( + QUARKUS_ALL_ANNOTATION, + target, + Collections.emptyList())); + } + } + + private void addAllAnnotationOnMethodListParameters(Set annotationsToAdd, MethodInfo methodInfo) { + // in Spring List means that all instances of SomeBean should be injected + List parameters = methodInfo.parameterTypes(); + for (int i = 0; i < parameters.size(); i++) { + Type parameter = parameters.get(i); + if (parameter.name().equals(DotNames.LIST)) { + annotationsToAdd.add(create( + QUARKUS_ALL_ANNOTATION, + MethodParameterInfo.create(methodInfo, (short) i), + Collections.emptyList())); + } + } + } + /** * Meant to be called with instances of @Component, @Service, @Repository */ diff --git a/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java b/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java index 3af74b8d00ec6..3ca3adfe50c4c 100644 --- a/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java +++ b/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java @@ -19,16 +19,22 @@ public class ListOfBeansTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addClasses(Foo.class, ServiceAlpha.class, ServiceBravo.class, Service.class, + .addClasses(Foo.class, Bar.class, ServiceAlpha.class, ServiceBravo.class, Service.class, Converter.class, ConverterAlpha.class, ConverterBravo.class)); @Inject Foo foo; + @Inject + Bar bar; + @Test public void testInjection() { assertThat(foo.services).hasSize(2).extractingResultOf("ping").containsExactlyInAnyOrder("alpha", "bravo"); assertThat(foo.converters).hasSize(2).extractingResultOf("pong").containsExactlyInAnyOrder("alpha", "bravo"); + + assertThat(bar.services).hasSize(2).extractingResultOf("ping").containsExactlyInAnyOrder("alpha", "bravo"); + assertThat(bar.converters).hasSize(2).extractingResultOf("pong").containsExactlyInAnyOrder("alpha", "bravo"); } @org.springframework.stereotype.Service @@ -43,6 +49,23 @@ public static class Foo { Foo(List converters) { this.converters = converters; } + } + + /** + * Test Spring with JSR-303 support + */ + @org.springframework.stereotype.Service + public static class Bar { + + @Inject + List services; + + final List converters; + + @Inject + Bar(List converters) { + this.converters = converters; + } }