Bind to super types

This commit is contained in:
Kevin Wang
2019-10-23 10:22:13 -07:00
committed by Taylor Wicksell
parent d62d78e500
commit dc2a0b6495
2 changed files with 112 additions and 22 deletions

View File

@@ -152,9 +152,9 @@ public class SpringModule extends AbstractModule {
if (!clazz.isInterface() && !ClassUtils.isCglibProxyClass(clazz)) {
bindConditionally(binder(), name, clazz, typeProvider, namedProvider, bindingAnnotation);
}
for (Type iface : getAllSuperInterfaces(type, clazz)) {
if (!ClassUtils.isCglibProxyClassName(iface.getTypeName())) {
bindConditionally(binder(), name, iface, typeProvider, namedProvider, bindingAnnotation);
for (Type superType : getAllSuperTypes(type, clazz)) {
if (!ClassUtils.isCglibProxyClassName(superType.getTypeName())) {
bindConditionally(binder(), name, superType, typeProvider, namedProvider, bindingAnnotation);
}
}
for (Type iface : clazz.getGenericInterfaces()) {
@@ -242,7 +242,7 @@ public class SpringModule extends AbstractModule {
return Arrays.equals(candidate.getParameterTypes(), current.getParameterTypes());
}
private static Set<Type> getAllSuperInterfaces(Type originalType, Class clazz) {
private static Set<Type> getAllSuperTypes(Type originalType, Class clazz) {
Set<Type> allInterfaces = new HashSet<>();
TypeLiteral typeToken = TypeLiteral.get(originalType);
Queue<Type> queue = new LinkedList<>();
@@ -256,13 +256,17 @@ public class SpringModule extends AbstractModule {
if (type instanceof Class) {
for (Type i : ((Class) type).getInterfaces()) {
if (i instanceof Class && ((Class) i).isAssignableFrom(typeToken.getRawType())) {
Type superType = typeToken.getSupertype((Class) i).getType();
queue.add(superType);
if (!(superType instanceof Class)) {
Type superInterface = typeToken.getSupertype((Class) i).getType();
queue.add(superInterface);
if (!(superInterface instanceof Class)) {
queue.add(i);
}
}
}
if (((Class) type).getSuperclass() != null && ((Class) type).isAssignableFrom(typeToken.getRawType())) {
Type superClass = typeToken.getSupertype(((Class) type).getSuperclass()).getType();
queue.add(superClass);
}
}
}
return allInterfaces;

View File

@@ -157,36 +157,108 @@ public class SuperClassTests {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
IFoo iFoo = context.getBean(IFoo.class);
assertTrue(iFoo instanceof Foo);
assertTrue(iFoo instanceof SubFoo);
Foo foo = context.getBean(Foo.class);
assertTrue(foo instanceof SubFoo);
}
@Test
public void testGuiceClass() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
baseTestGuiceClass(ModulesConfig.class);
}
@Test
public void testImportGuiceClass() {
baseTestGuiceClass(ImportConfig.class);
}
@Test
public void testComponentScanGuiceClass() {
baseTestGuiceClass(ComponentScanConfig.class);
}
private void baseTestGuiceClass(Class configClass) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
Injector injector = context.getBean(Injector.class);
IFoo iFoo = injector.getInstance(IFoo.class);
assertTrue(iFoo instanceof Foo);
assertTrue(iFoo instanceof SubFoo);
Foo foo = injector.getInstance(Foo.class);
assertTrue(foo instanceof SubFoo);
}
@Test
public void testSpringClassWithType() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
baseTestSpringClassWithType(ModulesConfig.class);
}
@Test
public void testImportSpringClassWithType() {
baseTestSpringClassWithType(ImportConfig.class);
}
@Test
public void testComponentScanSpringClassWithType() {
baseTestSpringClassWithType(ComponentScanConfig.class);
}
private void baseTestSpringClassWithType(Class configClass) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
String[] stringBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, String.class));
assertEquals(1, stringBeanNames.length);
assertTrue(context.getBean(stringBeanNames[0]) instanceof StringFoo);
assertTrue(context.getBean(stringBeanNames[0]) instanceof SubStringFoo);
stringBeanNames = context.getBeanNamesForType(StringFoo.class);
assertEquals(1, stringBeanNames.length);
assertTrue(context.getBean(stringBeanNames[0]) instanceof StringFoo);
assertTrue(context.getBean(stringBeanNames[0]) instanceof SubStringFoo);
String[] integerBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, Integer.class));
assertEquals(1, integerBeanNames.length);
assertTrue(context.getBean(integerBeanNames[0]) instanceof IntegerFoo);
assertTrue(context.getBean(integerBeanNames[0]) instanceof SubIntegerFoo);
integerBeanNames = context.getBeanNamesForType(IntegerFoo.class);
assertEquals(1, integerBeanNames.length);
assertTrue(context.getBean(integerBeanNames[0]) instanceof IntegerFoo);
assertTrue(context.getBean(integerBeanNames[0]) instanceof SubIntegerFoo);
}
@Test
public void testGuiceClassWithType() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
baseTestGuiceClassWithType(ModulesConfig.class);
}
@Test
public void testImportGuiceClassWithType() {
baseTestGuiceClassWithType(ImportConfig.class);
}
@Test
public void testComponentScanGuiceClassWithType() {
baseTestGuiceClassWithType(ComponentScanConfig.class);
}
private void baseTestGuiceClassWithType(Class configClass) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
Injector injector = context.getBean(Injector.class);
IFooWithType<String> stringFoo = injector.getInstance(Key.get(new TypeLiteral<IFooWithType<String>>(){}));
assertTrue(stringFoo instanceof StringFoo);
IFooWithType<Integer> integerFoo = injector.getInstance(Key.get(new TypeLiteral<IFooWithType<Integer>>(){}));
assertTrue(integerFoo instanceof IntegerFoo);
IFooWithType<String> iFooWithTypeString = injector.getInstance(Key.get(new TypeLiteral<IFooWithType<String>>(){}));
assertTrue(iFooWithTypeString instanceof StringFoo);
assertTrue(iFooWithTypeString instanceof SubStringFoo);
StringFoo stringFoo = injector.getInstance(StringFoo.class);
assertTrue(stringFoo instanceof SubStringFoo);
IFooWithType<Integer> iFooWithTypeInteger = injector.getInstance(Key.get(new TypeLiteral<IFooWithType<Integer>>(){}));
assertTrue(iFooWithTypeInteger instanceof IntegerFoo);
assertTrue(iFooWithTypeInteger instanceof SubIntegerFoo);
IntegerFoo integerFoo = injector.getInstance(IntegerFoo.class);
assertTrue(integerFoo instanceof SubIntegerFoo);
}
static class DisableJITConfig {
@@ -220,19 +292,18 @@ public class SuperClassTests {
return new IGrandChildInteger();
}
@Bean
public Foo iFoo() {
return new Foo();
public SubFoo subFoo() {
return new SubFoo();
}
@Bean
public StringFoo stringFoo() {
return new StringFoo();
public SubStringFoo stringFoo() {
return new SubStringFoo();
}
@Bean IntegerFoo integerFoo() {
return new IntegerFoo();
@Bean SubIntegerFoo integerFoo() {
return new SubIntegerFoo();
}
@@ -240,7 +311,7 @@ public class SuperClassTests {
@Configuration
@EnableGuiceModules
@Import({IGrandChildImpl.class, IGrandChildString.class, IGrandChildInteger.class})
@Import({IGrandChildImpl.class, IGrandChildString.class, IGrandChildInteger.class, SubFoo.class, SubStringFoo.class, SubIntegerFoo.class})
static class ImportConfig extends DisableJITConfig {
}
@@ -299,6 +370,11 @@ public class SuperClassTests {
}
@Component
public static class SubFoo extends Foo {
}
public interface IFooWithType<T> {
}
@@ -307,8 +383,18 @@ public class SuperClassTests {
}
@Component
public static class SubStringFoo extends StringFoo {
}
public static class IntegerFoo implements IFooWithType<Integer> {
}
@Component
public static class SubIntegerFoo extends IntegerFoo {
}
}