fix: Guice Cannot Inject Beans with Custom Annotations
SpringModule binds custom guice Providers for Spring managed beans so that Guice can inject beans from Spring Context. Due to a bug in the Provider, Guice can only inject Spring beans that either don't have any qualifier annotations or only have Named annotation as a qualifier. This fix enables Guice to inject beans with custom qualifier annotations as well. Custom qualifier annotations do not need to be marker annotations (in other words, they can have attributes). Other changes include: Using factory method metadata of annotated bean definition rather than using custom code to retrieve factory method and its annotations Added more test cases to validate various qualifier annotation scenarios.
This commit is contained in:
committed by
Dave Syer
parent
e133fee483
commit
ce15b8e580
@@ -16,7 +16,12 @@
|
||||
|
||||
package org.springframework.guice.module;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
import com.google.inject.ConfigurationException;
|
||||
import com.google.inject.Guice;
|
||||
@@ -35,6 +40,7 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
@@ -68,6 +74,43 @@ public class SpringModuleMetadataTests {
|
||||
assertThat(injector.getInstance(Key.get(Service.class, Names.named("service")))).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void threeServicesByQualifier() throws Exception {
|
||||
Injector injector = createInjector(PrimaryConfig.class, QualifiedConfig.class);
|
||||
|
||||
assertThat(injector.getInstance(
|
||||
Key.get(Service.class, ServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class))))
|
||||
.extracting("name").isEqualTo("emptyQualifierService");
|
||||
|
||||
assertThat(injector.getInstance(
|
||||
Key.get(Service.class, EmptyServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class))))
|
||||
.extracting("name").isEqualTo("emptyQualifierService");
|
||||
|
||||
assertThat(injector.getInstance(
|
||||
Key.get(Service.class, MyServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class))))
|
||||
.extracting("name").isEqualTo("myService");
|
||||
|
||||
assertThat(injector.getInstance(Key.get(Service.class, Names.named("namedService")))).extracting("name")
|
||||
.isEqualTo("namedService");
|
||||
|
||||
assertThat(injector.getInstance(Key.get(Service.class, Names.named("namedServiceWithADifferentBeanName"))))
|
||||
.extracting("name").isEqualTo("namedServiceWithADifferentBeanName");
|
||||
|
||||
assertThat(injector.getInstance(Service.class)).extracting("name").isEqualTo("primary");
|
||||
|
||||
// Test cases where we don't expect to find any bindings
|
||||
assertThatCode(() -> injector.getInstance(Key.get(Service.class, Names.named("randomService"))))
|
||||
.isInstanceOf(ConfigurationException.class);
|
||||
|
||||
assertThatCode(() -> injector.getInstance(
|
||||
Key.get(Service.class, NoServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class))))
|
||||
.isInstanceOf(ConfigurationException.class);
|
||||
|
||||
assertThatCode(() -> injector.getInstance(Key.get(Service.class, UnboundServiceQualifier.class)))
|
||||
.isInstanceOf(ConfigurationException.class);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includes() throws Exception {
|
||||
Injector injector = createInjector(TestConfig.class, MetadataIncludesConfig.class);
|
||||
@@ -92,10 +135,23 @@ public class SpringModuleMetadataTests {
|
||||
|
||||
interface Service {
|
||||
|
||||
String getName();
|
||||
|
||||
}
|
||||
|
||||
protected static class MyService implements Service {
|
||||
|
||||
private final String name;
|
||||
|
||||
protected MyService(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
@@ -135,7 +191,7 @@ public class SpringModuleMetadataTests {
|
||||
|
||||
@Bean
|
||||
public Service service() {
|
||||
return new MyService();
|
||||
return new MyService("service");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -146,7 +202,7 @@ public class SpringModuleMetadataTests {
|
||||
@Bean
|
||||
@Primary
|
||||
public Service primary() {
|
||||
return new MyService();
|
||||
return new MyService("primary");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,7 +212,36 @@ public class SpringModuleMetadataTests {
|
||||
|
||||
@Bean
|
||||
public Service more() {
|
||||
return new MyService();
|
||||
return new MyService("more");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class QualifiedConfig {
|
||||
|
||||
@Bean
|
||||
@Named("namedService")
|
||||
public Service namedService() {
|
||||
return new MyService("namedService");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Named("namedServiceWithADifferentBeanName")
|
||||
public Service anotherNamedService() {
|
||||
return new MyService("namedServiceWithADifferentBeanName");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ServiceQualifier
|
||||
public Service emptyQualifierService() {
|
||||
return new MyService("emptyQualifierService");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ServiceQualifier(type = "myService")
|
||||
public Service myService(@Named("namedService") Service service) {
|
||||
return new MyService("myService");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -166,4 +251,38 @@ public class SpringModuleMetadataTests {
|
||||
|
||||
}
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ServiceQualifier {
|
||||
|
||||
String type() default "";
|
||||
|
||||
}
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface UnboundServiceQualifier {
|
||||
|
||||
}
|
||||
|
||||
@ServiceQualifier
|
||||
interface ServiceQualifierAnnotated {
|
||||
|
||||
}
|
||||
|
||||
@ServiceQualifier(type = "")
|
||||
interface EmptyServiceQualifierAnnotated {
|
||||
|
||||
}
|
||||
|
||||
@ServiceQualifier(type = "myService")
|
||||
interface MyServiceQualifierAnnotated {
|
||||
|
||||
}
|
||||
|
||||
@ServiceQualifier(type = "noService")
|
||||
interface NoServiceQualifierAnnotated {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user