Skip to content

Commit

Permalink
Support injecting a list of Spring beans
Browse files Browse the repository at this point in the history
This is now possible due to the existence of
Arc's `@All`

Fixes: quarkusio#5668
  • Loading branch information
geoand committed Apr 12, 2022
1 parent 27470be commit 282ab1c
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
5 changes: 5 additions & 0 deletions extensions/spring-di/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.Type;

import io.quarkus.arc.deployment.AdditionalStereotypeBuildItem;
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
Expand Down Expand Up @@ -76,6 +78,7 @@ public class SpringDIProcessor {
private static final DotName CDI_NAMED_ANNOTATION = DotNames.NAMED;
private static final DotName CDI_INJECT_ANNOTATION = DotNames.INJECT;
private static final DotName CDI_PRODUCES_ANNOTATION = DotNames.PRODUCES;
private static final DotName QUARKUS_ALL_ANNOTATION = DotNames.ALL;
private static final DotName MP_CONFIG_PROPERTY_ANNOTATION = DotName.createSimple(ConfigProperty.class.getName());

@BuildStep
Expand Down Expand Up @@ -384,6 +387,14 @@ Set<AnnotationInstance> getAnnotationsToAdd(
Collections.singletonList((AnnotationValue.createStringValue("value", value)))));
}
}

// in Spring List<SomeBean> 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()));
}
} else if (fieldInfo.hasAnnotation(SPRING_VALUE_ANNOTATION)) {
final AnnotationInstance annotation = fieldInfo.annotation(SPRING_VALUE_ANNOTATION);
addSpringValueAnnotations(target, annotation, true, annotationsToAdd);
Expand Down Expand Up @@ -418,6 +429,18 @@ Set<AnnotationInstance> getAnnotationsToAdd(
CDI_INJECT_ANNOTATION,
target,
Collections.emptyList()));
// in Spring List<SomeBean> means that all instances of SomeBean should be injected
List<Type> parameters = methodInfo.parameters();
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()));
}
}

}

// add method parameter conversion annotations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package io.quarkus.spring.di.deployment;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

import java.util.List;

import javax.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import io.quarkus.test.QuarkusUnitTest;

public class ListOfBeansTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(Foo.class, ServiceAlpha.class, ServiceBravo.class, Service.class,
Converter.class, ConverterAlpha.class, ConverterBravo.class));

@Inject
Foo foo;

@Test
public void testInjection() {
assertThat(foo.services).hasSize(2).extractingResultOf("ping").containsExactlyInAnyOrder("alpha", "bravo");
assertThat(foo.converters).hasSize(2).extractingResultOf("pong").containsExactlyInAnyOrder("alpha", "bravo");
}

@org.springframework.stereotype.Service
public static class Foo {

@Autowired
List<Service> services;

final List<Converter> converters;

@Autowired
Foo(List<Converter> converters) {
this.converters = converters;
}

}

public interface Service {

String ping();
}

public interface Converter {

String pong();
}

@Component
public static class ServiceAlpha implements Service {

public String ping() {
return "alpha";
}
}

@Component
public static class ServiceBravo implements Service {

public String ping() {
return "bravo";
}
}

@org.springframework.stereotype.Service
public static class ConverterAlpha implements Converter {

@Override
public String pong() {
return "alpha";
}

}

@Repository
public static class ConverterBravo implements Converter {

@Override
public String pong() {
return "bravo";
}

}
}

0 comments on commit 282ab1c

Please sign in to comment.