Support generic interfaces
This commit is contained in:
committed by
Taylor Wicksell
parent
4308f7498b
commit
1e7cbb0e31
@@ -13,17 +13,6 @@
|
||||
|
||||
package org.springframework.guice.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.inject.Binding;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
@@ -31,13 +20,11 @@ import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.Stage;
|
||||
import com.google.inject.internal.LinkedBindingImpl;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.spi.Element;
|
||||
import com.google.inject.spi.ElementSource;
|
||||
import com.google.inject.spi.Elements;
|
||||
import com.google.inject.spi.PrivateElements;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -55,10 +42,19 @@ import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.guice.module.SpringModule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Configuration postprocessor that registers all the bindings in Guice modules as Spring
|
||||
* beans.
|
||||
|
||||
@@ -13,21 +13,6 @@
|
||||
|
||||
package org.springframework.guice.module;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Injector;
|
||||
@@ -40,20 +25,38 @@ import com.google.inject.matcher.Matchers;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.name.Names;
|
||||
import com.google.inject.spi.ProvisionListener;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.core.type.StandardMethodMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -114,23 +117,31 @@ public class SpringModule extends AbstractModule {
|
||||
Optional<Annotation> bindingAnnotation = getAnnotationForBeanDefinition(definition, beanFactory);
|
||||
if (definition.isAutowireCandidate()
|
||||
&& definition.getRole() == AbstractBeanDefinition.ROLE_APPLICATION) {
|
||||
Class<?> type = beanFactory.getType(name);
|
||||
Type type;
|
||||
RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(name);
|
||||
if (rootBeanDefinition.getFactoryBeanName() != null && rootBeanDefinition.getResolvedFactoryMethod() != null) {
|
||||
type = rootBeanDefinition.getResolvedFactoryMethod().getGenericReturnType();
|
||||
} else {
|
||||
type = rootBeanDefinition.getResolvableType().getType();
|
||||
}
|
||||
if (type == null) {
|
||||
continue;
|
||||
}
|
||||
final String beanName = name;
|
||||
Provider<?> typeProvider = BeanFactoryProvider.typed(beanFactory, type, bindingAnnotation);
|
||||
Provider<?> namedProvider = BeanFactoryProvider.named(beanFactory,
|
||||
Provider typeProvider = BeanFactoryProvider.typed(beanFactory, type, bindingAnnotation);
|
||||
Provider namedProvider = BeanFactoryProvider.named(beanFactory,
|
||||
beanName, type, bindingAnnotation);
|
||||
if (!type.isInterface() && !ClassUtils.isCglibProxyClass(type)) {
|
||||
bindConditionally(binder(), name, type, typeProvider, namedProvider, bindingAnnotation);
|
||||
|
||||
Class clazz = (type instanceof Class) ? (Class) type : beanFactory.getType(beanName);
|
||||
if (!clazz.isInterface() && !ClassUtils.isCglibProxyClass(clazz)) {
|
||||
bindConditionally(binder(), name, clazz, typeProvider, namedProvider, bindingAnnotation);
|
||||
}
|
||||
for (Class<?> iface : getAllSuperInterfaces(new Class[]{type})) {
|
||||
if (!ClassUtils.isCglibProxyClass(iface)) {
|
||||
for (Type iface : getAllSuperInterfaces(type, clazz)) {
|
||||
if (!ClassUtils.isCglibProxyClassName(iface.getTypeName())) {
|
||||
bindConditionally(binder(), name, iface, typeProvider, namedProvider, bindingAnnotation);
|
||||
}
|
||||
}
|
||||
for (Type iface : type.getGenericInterfaces()) {
|
||||
for (Type iface : clazz.getGenericInterfaces()) {
|
||||
bindConditionally(binder(), name, iface, typeProvider, namedProvider, bindingAnnotation);
|
||||
}
|
||||
}
|
||||
@@ -215,17 +226,33 @@ public class SpringModule extends AbstractModule {
|
||||
return Arrays.equals(candidate.getParameterTypes(), current.getParameterTypes());
|
||||
}
|
||||
|
||||
private static Class[] getAllSuperInterfaces(Class[] childInterfaces) {
|
||||
List<Class> allInterfaces = new LinkedList<>();
|
||||
for (Class childInterface : childInterfaces) {
|
||||
allInterfaces.add(childInterface);
|
||||
allInterfaces.addAll(
|
||||
Arrays.asList(
|
||||
getAllSuperInterfaces(childInterface.getInterfaces())));
|
||||
private static Set<Type> getAllSuperInterfaces(Type originalType, Class clazz) {
|
||||
Set<Type> allInterfaces = new HashSet<>();
|
||||
TypeLiteral typeToken = TypeLiteral.get(originalType);
|
||||
Queue<Type> queue = new LinkedList<>();
|
||||
queue.add(clazz);
|
||||
if (originalType != clazz) {
|
||||
queue.add(originalType);
|
||||
}
|
||||
return allInterfaces.toArray(new Class[0]);
|
||||
while (!queue.isEmpty()) {
|
||||
Type type = queue.poll();
|
||||
allInterfaces.add(type);
|
||||
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)) {
|
||||
queue.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allInterfaces;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void bindConditionally(Binder binder, String name, Type type,
|
||||
Provider typeProvider, Provider namedProvider, Optional<Annotation> bindingAnnotation) {
|
||||
@@ -299,42 +326,42 @@ public class SpringModule extends AbstractModule {
|
||||
}
|
||||
}
|
||||
|
||||
private static class BeanFactoryProvider<T> implements Provider<T> {
|
||||
private static class BeanFactoryProvider implements Provider {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private String name;
|
||||
|
||||
private Class<T> type;
|
||||
private Type type;
|
||||
|
||||
private T result;
|
||||
private Object result;
|
||||
|
||||
private Optional<Annotation> bindingAnnotation;
|
||||
|
||||
private BeanFactoryProvider(ConfigurableListableBeanFactory beanFactory,
|
||||
String name, Class<T> type, Optional<Annotation> bindingAnnotation) {
|
||||
String name, Type type, Optional<Annotation> bindingAnnotation) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.name = name;
|
||||
this.bindingAnnotation = bindingAnnotation;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static <S> Provider<S> named(ConfigurableListableBeanFactory beanFactory,
|
||||
String name, Class<S> type, Optional<Annotation> bindingAnnotation) {
|
||||
return new BeanFactoryProvider<S>(beanFactory, name, type, bindingAnnotation);
|
||||
public static Provider named(ConfigurableListableBeanFactory beanFactory,
|
||||
String name, Type type, Optional<Annotation> bindingAnnotation) {
|
||||
return new BeanFactoryProvider(beanFactory, name, type, bindingAnnotation);
|
||||
}
|
||||
|
||||
public static <S> Provider<S> typed(ConfigurableListableBeanFactory beanFactory,
|
||||
Class<S> type, Optional<Annotation> bindingAnnotation) {
|
||||
return new BeanFactoryProvider<S>(beanFactory, null, type, bindingAnnotation);
|
||||
public static Provider typed(ConfigurableListableBeanFactory beanFactory,
|
||||
Type type, Optional<Annotation> bindingAnnotation) {
|
||||
return new BeanFactoryProvider(beanFactory, null, type, bindingAnnotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
public Object get() {
|
||||
if (this.result == null) {
|
||||
|
||||
String[] named = BeanFactoryUtils
|
||||
.beanNamesForTypeIncludingAncestors(this.beanFactory, this.type);
|
||||
.beanNamesForTypeIncludingAncestors(this.beanFactory, ResolvableType.forType(type));
|
||||
List<String> names = new ArrayList<String>(named.length);
|
||||
if (named.length == 1) {
|
||||
names.add(named[0]);
|
||||
@@ -355,12 +382,12 @@ public class SpringModule extends AbstractModule {
|
||||
}
|
||||
}
|
||||
if (names.size() == 1) {
|
||||
this.result = this.beanFactory.getBean(names.get(0), this.type);
|
||||
this.result = this.beanFactory.getBean(names.get(0));
|
||||
}
|
||||
else {
|
||||
for (String name : named) {
|
||||
if (this.beanFactory.getBeanDefinition(name).isPrimary()) {
|
||||
this.result = this.beanFactory.getBean(name, this.type);
|
||||
this.result = this.beanFactory.getBean(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,154 @@ package org.springframework.guice;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.guice.annotation.EnableGuiceModules;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SuperClassTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpringInterface() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
|
||||
IParent iParent = context.getBean(IParent.class);
|
||||
assertTrue(iParent instanceof IChildImpl);
|
||||
baseTestSpringInterface(ModulesConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportSpringInterface() {
|
||||
baseTestSpringInterface(ImportConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentScanSpringInterface() {
|
||||
baseTestSpringInterface(ComponentScanConfig.class);
|
||||
}
|
||||
|
||||
private void baseTestSpringInterface(Class configClass) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
|
||||
assertTrue(context.getBean(IParent.class) instanceof IGrandChildImpl);
|
||||
assertTrue(context.getBean(IChild.class) instanceof IGrandChildImpl);
|
||||
assertTrue(context.getBean(IGrandChild.class) instanceof IGrandChildImpl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGuiceInterface() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
|
||||
baseTestGuiceInterface(ModulesConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportGuiceInterface() {
|
||||
baseTestGuiceInterface(ImportConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentScanGuiceInterface() {
|
||||
baseTestGuiceInterface(ComponentScanConfig.class);
|
||||
}
|
||||
|
||||
private void baseTestGuiceInterface(Class configClass) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
|
||||
Injector injector = context.getBean(Injector.class);
|
||||
IParent iParent = injector.getInstance(IParent.class);
|
||||
assertTrue(iParent instanceof IChildImpl);
|
||||
assertTrue(injector.getInstance(IParent.class) instanceof IGrandChildImpl);
|
||||
assertTrue(injector.getInstance(IChild.class) instanceof IGrandChildImpl);
|
||||
assertTrue(injector.getInstance(IGrandChild.class) instanceof IGrandChildImpl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringInterfaceWithType() {
|
||||
baseTestSpringInterfaceWithType(ModulesConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportSpringInterfaceWithType() {
|
||||
baseTestSpringInterfaceWithType(ImportConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentScanSpringInterfaceWithType() {
|
||||
baseTestSpringInterfaceWithType(ComponentScanConfig.class);
|
||||
}
|
||||
|
||||
private void baseTestSpringInterfaceWithType(Class configClass) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
|
||||
|
||||
String[] allParentBeanNames = context.getBeanNamesForType(IParentWithType.class);
|
||||
assertEquals(2, allParentBeanNames.length);
|
||||
|
||||
String[] stringParentBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IParentWithType.class, String.class));
|
||||
assertEquals(1, stringParentBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IGrandChildWithType<String>>() {}.getRawType().isInstance(context.getBean(stringParentBeanNames[0])));
|
||||
|
||||
String[] integerParentBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IParentWithType.class, Integer.class));
|
||||
assertEquals(1, integerParentBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IGrandChildWithType<Integer>>() {}.getRawType().isInstance(context.getBean(integerParentBeanNames[0])));
|
||||
|
||||
String[] allChildBeanNames = context.getBeanNamesForType(IChildWithType.class);
|
||||
assertEquals(2, allChildBeanNames.length);
|
||||
|
||||
String[] stringChildBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IChildWithType.class, String.class));
|
||||
assertEquals(1, stringChildBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IChildWithType<String>>() {}.getRawType().isInstance(context.getBean(stringChildBeanNames[0])));
|
||||
|
||||
String[] integerChildBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IChildWithType.class, Integer.class));
|
||||
assertEquals(1, integerChildBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IChildWithType<Integer>>() {}.getRawType().isInstance(context.getBean(integerChildBeanNames[0])));
|
||||
|
||||
String[] allGrandChildBeanNames = context.getBeanNamesForType(IGrandChildWithType.class);
|
||||
assertEquals(2, allGrandChildBeanNames.length);
|
||||
|
||||
String[] stringGrandChildBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IGrandChildWithType.class, String.class));
|
||||
assertEquals(1, stringGrandChildBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IGrandChildWithType<String>>() {}.getRawType().isInstance(context.getBean(stringGrandChildBeanNames[0])));
|
||||
|
||||
String[] integerGrandChildBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IGrandChildWithType.class, Integer.class));
|
||||
assertEquals(1, integerGrandChildBeanNames.length);
|
||||
assertTrue(new TypeLiteral<IGrandChildWithType<Integer>>() {}.getRawType().isInstance(context.getBean(integerGrandChildBeanNames[0])));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGuiceInterfaceWithType() {
|
||||
baseTestGuiceInterfaceWithType(ModulesConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportGuiceInterfaceWithType() {
|
||||
baseTestGuiceInterfaceWithType(ImportConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentScanGuiceInterfaceWithType() {
|
||||
baseTestGuiceInterfaceWithType(ComponentScanConfig.class);
|
||||
}
|
||||
|
||||
private void baseTestGuiceInterfaceWithType(Class configClass) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass);
|
||||
Injector injector = context.getBean(Injector.class);
|
||||
IParentWithType<String> iParentString = injector.getInstance(Key.get(new TypeLiteral<IParentWithType<String>>(){}));
|
||||
assertTrue(iParentString instanceof IGrandChildString);
|
||||
IParentWithType<Integer> iParentInteger = injector.getInstance(Key.get(new TypeLiteral<IParentWithType<Integer>>(){}));
|
||||
assertTrue(iParentInteger instanceof IGrandChildInteger);
|
||||
|
||||
IChildWithType<String> iChildString = injector.getInstance(Key.get(new TypeLiteral<IChildWithType<String>>(){}));
|
||||
assertTrue(iChildString instanceof IGrandChildString);
|
||||
IChildWithType<Integer> iChildInteger = injector.getInstance(Key.get(new TypeLiteral<IChildWithType<Integer>>(){}));
|
||||
assertTrue(iChildInteger instanceof IGrandChildInteger);
|
||||
|
||||
IGrandChildWithType<String> iGrandChildString = injector.getInstance(Key.get(new TypeLiteral<IGrandChildWithType<String>>(){}));
|
||||
assertTrue(iGrandChildString instanceof IGrandChildString);
|
||||
IGrandChildWithType<Integer> iGrandChildInteger = injector.getInstance(Key.get(new TypeLiteral<IGrandChildWithType<Integer>>(){}));
|
||||
assertTrue(iGrandChildInteger instanceof IGrandChildInteger);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -42,20 +167,29 @@ public class SuperClassTests {
|
||||
assertTrue(iFoo instanceof Foo);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGuiceModules
|
||||
static class ModulesConfig {
|
||||
@Test
|
||||
public void testSpringClassWithType() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
|
||||
String[] stringBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, String.class));
|
||||
assertEquals(1, stringBeanNames.length);
|
||||
assertTrue(context.getBean(stringBeanNames[0]) instanceof StringFoo);
|
||||
|
||||
@Bean
|
||||
public IChild iChild() {
|
||||
return new IChildImpl();
|
||||
}
|
||||
String[] integerBeanNames = context.getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, Integer.class));
|
||||
assertEquals(1, integerBeanNames.length);
|
||||
assertTrue(context.getBean(integerBeanNames[0]) instanceof IntegerFoo);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Foo iFoo() {
|
||||
return new Foo();
|
||||
}
|
||||
@Test
|
||||
public void testGuiceClassWithType() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class);
|
||||
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);
|
||||
}
|
||||
|
||||
static class DisableJITConfig {
|
||||
@Bean
|
||||
public AbstractModule disableJITModule() {
|
||||
return new AbstractModule() {
|
||||
@@ -67,6 +201,55 @@ public class SuperClassTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGuiceModules
|
||||
static class ModulesConfig extends DisableJITConfig {
|
||||
|
||||
@Bean
|
||||
public IGrandChild iGrandChild() {
|
||||
return new IGrandChildImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IGrandChildWithType<String> iChildString() {
|
||||
return new IGrandChildString();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IGrandChildWithType<Integer> iChildInteger() {
|
||||
return new IGrandChildInteger();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Foo iFoo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StringFoo stringFoo() {
|
||||
return new StringFoo();
|
||||
}
|
||||
|
||||
@Bean IntegerFoo integerFoo() {
|
||||
return new IntegerFoo();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGuiceModules
|
||||
@Import({IGrandChildImpl.class, IGrandChildString.class, IGrandChildInteger.class})
|
||||
static class ImportConfig extends DisableJITConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGuiceModules
|
||||
@ComponentScan(basePackageClasses = ComponentScanConfig.class, resourcePattern = "**/SuperClassTests**.class",
|
||||
excludeFilters = {@ComponentScan.Filter(Configuration.class)})
|
||||
static class ComponentScanConfig extends DisableJITConfig {
|
||||
}
|
||||
|
||||
public interface IParent {
|
||||
}
|
||||
@@ -75,10 +258,39 @@ public class SuperClassTests {
|
||||
|
||||
}
|
||||
|
||||
public static class IChildImpl implements IChild {
|
||||
public interface IGrandChild extends IChild {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class IGrandChildImpl implements IGrandChild {
|
||||
|
||||
}
|
||||
|
||||
public interface IParentWithType<T> {
|
||||
|
||||
}
|
||||
|
||||
public interface IChildWithType<T> extends IParentWithType<T> {
|
||||
|
||||
}
|
||||
|
||||
public interface IGrandChildWithType<T> extends IChildWithType<T> {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class IGrandChildString implements IGrandChildWithType<String> {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class IGrandChildInteger implements IGrandChildWithType<Integer> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface IFoo {
|
||||
|
||||
}
|
||||
@@ -86,4 +298,17 @@ public class SuperClassTests {
|
||||
public static class Foo implements IFoo {
|
||||
|
||||
}
|
||||
|
||||
public interface IFooWithType<T> {
|
||||
|
||||
}
|
||||
|
||||
public static class StringFoo implements IFooWithType<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class IntegerFoo implements IFooWithType<Integer> {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user