diff --git a/src/main/java/org/springframework/guice/module/BeanFactoryProvider.java b/src/main/java/org/springframework/guice/module/BeanFactoryProvider.java index d1c24e2..6c00639 100644 --- a/src/main/java/org/springframework/guice/module/BeanFactoryProvider.java +++ b/src/main/java/org/springframework/guice/module/BeanFactoryProvider.java @@ -82,6 +82,7 @@ public class BeanFactoryProvider return new BeanFactoryProvider(config, null); } + @SuppressWarnings("unchecked") public BeanFactoryProvider initializer( ApplicationContextInitializer... initializers) { this.initializers.addAll(Arrays.asList(initializers)); diff --git a/src/main/java/org/springframework/guice/module/SpringModule.java b/src/main/java/org/springframework/guice/module/SpringModule.java index 5498d4c..f36c329 100644 --- a/src/main/java/org/springframework/guice/module/SpringModule.java +++ b/src/main/java/org/springframework/guice/module/SpringModule.java @@ -13,34 +13,6 @@ package org.springframework.guice.module; -import com.google.inject.AbstractModule; -import com.google.inject.Binder; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.ProvisionException; -import com.google.inject.Stage; -import com.google.inject.TypeLiteral; -import com.google.inject.internal.Annotations; -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; @@ -57,6 +29,36 @@ import java.util.Optional; import java.util.Queue; import java.util.Set; +import javax.inject.Provider; + +import com.google.inject.AbstractModule; +import com.google.inject.Binder; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.ProvisionException; +import com.google.inject.Stage; +import com.google.inject.TypeLiteral; +import com.google.inject.internal.Annotations; +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; + /** * @author Dave Syer * @@ -80,14 +82,16 @@ public class SpringModule extends AbstractModule { } public SpringModule(ApplicationContext context, boolean enableJustInTimeBinding) { - this((ConfigurableListableBeanFactory) context.getAutowireCapableBeanFactory(), enableJustInTimeBinding); + this((ConfigurableListableBeanFactory) context.getAutowireCapableBeanFactory(), + enableJustInTimeBinding); } public SpringModule(ConfigurableListableBeanFactory beanFactory) { this(beanFactory, true); } - public SpringModule(ConfigurableListableBeanFactory beanFactory, boolean enableJustInTimeBinding) { + public SpringModule(ConfigurableListableBeanFactory beanFactory, + boolean enableJustInTimeBinding) { this.beanFactory = beanFactory; this.enableJustInTimeBinding = enableJustInTimeBinding; } @@ -123,73 +127,92 @@ public class SpringModule extends AbstractModule { private void bind(ConfigurableListableBeanFactory beanFactory) { for (String name : beanFactory.getBeanDefinitionNames()) { BeanDefinition definition = beanFactory.getBeanDefinition(name); - + if (definition.hasAttribute(SPRING_GUICE_SOURCE)) { continue; } - Optional bindingAnnotation = getAnnotationForBeanDefinition(definition, beanFactory); + Optional bindingAnnotation = getAnnotationForBeanDefinition( + definition, beanFactory); if (definition.isAutowireCandidate() && definition.getRole() == AbstractBeanDefinition.ROLE_APPLICATION) { Type type; - RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(name); - if (rootBeanDefinition.getFactoryBeanName() != null && rootBeanDefinition.getResolvedFactoryMethod() != null) { - type = rootBeanDefinition.getResolvedFactoryMethod().getGenericReturnType(); - } else { + 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); - Class clazz = (type instanceof Class) ? (Class) type : beanFactory.getType(beanName); + Class clazz = (type instanceof Class) ? (Class) type + : beanFactory.getType(beanName); if (clazz == null) { continue; } if (!clazz.isInterface() && !ClassUtils.isCglibProxyClass(clazz)) { - bindConditionally(binder(), name, clazz, typeProvider, namedProvider, bindingAnnotation); + bindConditionally(binder(), name, clazz, typeProvider, namedProvider, + bindingAnnotation); } for (Type superType : getAllSuperTypes(type, clazz)) { if (!ClassUtils.isCglibProxyClassName(superType.getTypeName())) { - bindConditionally(binder(), name, superType, typeProvider, namedProvider, bindingAnnotation); + bindConditionally(binder(), name, superType, typeProvider, + namedProvider, bindingAnnotation); } } for (Type iface : clazz.getGenericInterfaces()) { - bindConditionally(binder(), name, iface, typeProvider, namedProvider, bindingAnnotation); + bindConditionally(binder(), name, iface, typeProvider, namedProvider, + bindingAnnotation); } } } } - private static String getNameFromBindingAnnotation(Optional bindingAnnotation) { + private static String getNameFromBindingAnnotation( + Optional bindingAnnotation) { if (bindingAnnotation.isPresent()) { Annotation annotation = bindingAnnotation.get(); if (annotation instanceof Named) { return ((Named) annotation).value(); - } else if (annotation instanceof javax.inject.Named) { + } + else if (annotation instanceof javax.inject.Named) { return ((javax.inject.Named) annotation).value(); - } else { + } + else { return null; } - } else { + } + else { return null; } } - - private static Optional getAnnotationForBeanDefinition(BeanDefinition definition, ConfigurableListableBeanFactory beanFactory) { + + private static Optional getAnnotationForBeanDefinition( + BeanDefinition definition, ConfigurableListableBeanFactory beanFactory) { if (definition instanceof AnnotatedBeanDefinition - && ((AnnotatedBeanDefinition) definition).getFactoryMethodMetadata() != null) { + && ((AnnotatedBeanDefinition) definition) + .getFactoryMethodMetadata() != null) { try { Method factoryMethod = getFactoryMethod(beanFactory, definition); return Arrays.stream(AnnotationUtils.getAnnotations(factoryMethod)) - .filter(a -> Annotations.isBindingAnnotation(a.annotationType())).findFirst(); - } catch (Exception e) { + .filter(a -> Annotations.isBindingAnnotation(a.annotationType())) + .findFirst(); + } + catch (Exception e) { return Optional.empty(); } - } else { + } + else { return Optional.empty(); } } @@ -211,7 +234,8 @@ public class SpringModule extends AbstractModule { return getFactoryMethod(definition, factoryClass); } - private static Method getFactoryMethod(BeanDefinition definition, Class factoryClass) { + private static Method getFactoryMethod(BeanDefinition definition, + Class factoryClass) { Method uniqueMethod = null; for (Method candidate : getCandidateFactoryMethods(definition, factoryClass)) { if (candidate.getName().equals(definition.getFactoryMethodName())) { @@ -242,9 +266,9 @@ public class SpringModule extends AbstractModule { return Arrays.equals(candidate.getParameterTypes(), current.getParameterTypes()); } - private static Set getAllSuperTypes(Type originalType, Class clazz) { + private static Set getAllSuperTypes(Type originalType, Class clazz) { Set allInterfaces = new HashSet<>(); - TypeLiteral typeToken = TypeLiteral.get(originalType); + TypeLiteral typeToken = TypeLiteral.get(originalType); Queue queue = new LinkedList<>(); queue.add(clazz); if (originalType != clazz) { @@ -254,17 +278,21 @@ public class SpringModule extends AbstractModule { 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 superInterface = typeToken.getSupertype((Class) i).getType(); + for (Type i : ((Class) type).getInterfaces()) { + if (i instanceof Class + && ((Class) i).isAssignableFrom(typeToken.getRawType())) { + 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(); + if (((Class) type).getSuperclass() != null + && ((Class) type).isAssignableFrom(typeToken.getRawType())) { + Type superClass = typeToken + .getSupertype(((Class) type).getSuperclass()).getType(); queue.add(superClass); } } @@ -272,10 +300,10 @@ public class SpringModule extends AbstractModule { return allInterfaces; } - @SuppressWarnings({ "rawtypes", "unchecked" }) private void bindConditionally(Binder binder, String name, Type type, - Provider typeProvider, Provider namedProvider, Optional bindingAnnotation) { + Provider typeProvider, Provider namedProvider, + Optional bindingAnnotation) { if (!this.matcher.matches(name, type)) { return; } @@ -290,13 +318,13 @@ public class SpringModule extends AbstractModule { } } } - Key key = bindingAnnotation.map(a ->(Key)Key.get(type, a)).orElse((Key)Key.get(type)); + Key key = bindingAnnotation.map(a -> (Key) Key.get(type, a)) + .orElse((Key) Key.get(type)); StageTypeKey stageTypeKey = new StageTypeKey(binder.currentStage(), key); if (this.bound.get(stageTypeKey) == null) { // Only bind one provider for each type - - binder.withSource(SPRING_GUICE_SOURCE).bind(key) - .toProvider(typeProvider); + + binder.withSource(SPRING_GUICE_SOURCE).bind(key).toProvider(typeProvider); this.bound.put(stageTypeKey, typeProvider); } // But allow binding to named beans if not already bound @@ -338,7 +366,8 @@ public class SpringModule extends AbstractModule { if (key == null) { if (other.key != null) return false; - } else if (!key.equals(other.key)) + } + else if (!key.equals(other.key)) return false; if (stage != other.stage) return false; @@ -346,7 +375,7 @@ public class SpringModule extends AbstractModule { } } - private static class BeanFactoryProvider implements Provider { + private static class BeanFactoryProvider implements Provider { private ConfigurableListableBeanFactory beanFactory; @@ -366,12 +395,12 @@ public class SpringModule extends AbstractModule { this.type = type; } - public static Provider named(ConfigurableListableBeanFactory beanFactory, + public static Provider named(ConfigurableListableBeanFactory beanFactory, String name, Type type, Optional bindingAnnotation) { return new BeanFactoryProvider(beanFactory, name, type, bindingAnnotation); } - public static Provider typed(ConfigurableListableBeanFactory beanFactory, + public static Provider typed(ConfigurableListableBeanFactory beanFactory, Type type, Optional bindingAnnotation) { return new BeanFactoryProvider(beanFactory, null, type, bindingAnnotation); } @@ -380,19 +409,28 @@ public class SpringModule extends AbstractModule { public Object get() { if (this.result == null) { - String[] named = BeanFactoryUtils - .beanNamesForTypeIncludingAncestors(this.beanFactory, ResolvableType.forType(type)); + String[] named = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( + this.beanFactory, ResolvableType.forType(type)); List names = new ArrayList(named.length); if (named.length == 1) { names.add(named[0]); } else { for (String name : named) { - if(bindingAnnotation.isPresent()) { - if (bindingAnnotation.get() instanceof Named || bindingAnnotation.get() instanceof javax.inject.Named) { - Optional annotation = SpringModule.getAnnotationForBeanDefinition(beanFactory.getMergedBeanDefinition(name), beanFactory); - String boundName = getNameFromBindingAnnotation(bindingAnnotation); - if(annotation.isPresent() && bindingAnnotation.get().equals(annotation.get()) || name.equals(boundName)) { + if (bindingAnnotation.isPresent()) { + if (bindingAnnotation.get() instanceof Named + || bindingAnnotation + .get() instanceof javax.inject.Named) { + Optional annotation = SpringModule + .getAnnotationForBeanDefinition( + beanFactory.getMergedBeanDefinition(name), + beanFactory); + String boundName = getNameFromBindingAnnotation( + bindingAnnotation); + if (annotation.isPresent() + && bindingAnnotation.get() + .equals(annotation.get()) + || name.equals(boundName)) { names.add(name); } } diff --git a/src/test/java/org/springframework/guice/ModuleFilteringTests.java b/src/test/java/org/springframework/guice/ModuleFilteringTests.java index 82290fc..0758f6c 100644 --- a/src/test/java/org/springframework/guice/ModuleFilteringTests.java +++ b/src/test/java/org/springframework/guice/ModuleFilteringTests.java @@ -1,20 +1,21 @@ package org.springframework.guice; -import static org.junit.Assert.assertNotNull; - -import com.google.inject.*; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Module; +import com.google.inject.Stage; import org.junit.AfterClass; import org.junit.Test; + import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.guice.ModuleFilteringTests.FilterThisModule; import org.springframework.guice.annotation.EnableGuiceModules; - import org.springframework.guice.annotation.InjectorFactory; -import java.util.List; +import static org.junit.Assert.assertNotNull; public class ModuleFilteringTests { @@ -33,19 +34,21 @@ public class ModuleFilteringTests { context.close(); } - @Test(expected=NoSuchBeanDefinitionException.class) + @Test(expected = NoSuchBeanDefinitionException.class) public void verifyFilteredModuleIsFiltered() { System.setProperty("spring.guice.modules.exclude", "FilterThisModule"); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( ModuleFilteringTestsConfig.class); try { - context.getBean(SomeInterface.class); - } finally { + context.getBean(SomeInterface.class); + } + finally { context.close(); } } - public static interface SomeInterface {} + public static interface SomeInterface { + } public static class SomeDependency implements SomeInterface { public SomeDependency() { diff --git a/src/test/java/org/springframework/guice/ProvidesSupplierWiringTests.java b/src/test/java/org/springframework/guice/ProvidesSupplierWiringTests.java index 0c43fd7..9146f5d 100644 --- a/src/test/java/org/springframework/guice/ProvidesSupplierWiringTests.java +++ b/src/test/java/org/springframework/guice/ProvidesSupplierWiringTests.java @@ -1,20 +1,22 @@ package org.springframework.guice; +import java.util.function.Supplier; + +import javax.inject.Singleton; + import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import org.junit.Ignore; import org.junit.Test; + import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.guice.annotation.EnableGuiceModules; import org.springframework.guice.injector.SpringInjector; -import javax.inject.Singleton; -import java.util.function.Supplier; - /** * Test Generics (e.g., Supplier) not losing type info across bridge in both directions * @@ -22,90 +24,99 @@ import java.util.function.Supplier; */ public class ProvidesSupplierWiringTests { - //Test Guice -> Spring direction - @Test - public void testProvidesSupplier() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class, FooBar.class); - Foo foo = (Foo)context.getBean(Foo.class); - Bar bar = (Bar)context.getBean(Bar.class); - } + // Test Guice -> Spring direction + @SuppressWarnings({ "resource", "unused" }) + @Test + public void testProvidesSupplier() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + ModulesConfig.class, FooBar.class); + Foo foo = context.getBean(Foo.class); + Bar bar = context.getBean(Bar.class); + } - @Configuration - @EnableGuiceModules - static class ModulesConfig { - @Bean - TestConfig testConfig() { - return new TestConfig(); - } - } + @Configuration + @EnableGuiceModules + static class ModulesConfig { + @Bean + TestConfig testConfig() { + return new TestConfig(); + } + } - @Configuration - static class FooBar { - @Bean - Foo foo(Supplier supplier) { - return supplier.get(); - } + @Configuration + static class FooBar { + @Bean + Foo foo(Supplier supplier) { + return supplier.get(); + } - @Bean - Bar bar(Supplier supplier) { - return supplier.get(); - } - } + @Bean + Bar bar(Supplier supplier) { + return supplier.get(); + } + } - static class TestConfig extends AbstractModule { - @Override - protected void configure() { - } + static class TestConfig extends AbstractModule { + @Override + protected void configure() { + } - @Singleton - @Provides - Supplier getFoo() { - return ()->new Foo(); - } + @Singleton + @Provides + Supplier getFoo() { + return () -> new Foo(); + } - @Singleton - @Provides - Supplier getBar() { - return ()->new Bar(); - } - } + @Singleton + @Provides + Supplier getBar() { + return () -> new Bar(); + } + } - static class Foo { - } + static class Foo { + } - static class Bar { + static class Bar { - } + } - //Test Spring -> Guice direction - //ToDo -- Today this direction doesn't work without further work. Ignore the test for now. - @Ignore - @Test - public void testProvidesSupplierSpring() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FooBarSpring.class); - SpringInjector injector = new SpringInjector(context); - Foo_Spring fooSpring = injector.getInstance(Key.get(new TypeLiteral>(){})).get(); - Bar_Spring barSpring = injector.getInstance(Key.get(new TypeLiteral>(){})).get(); - } + // Test Spring -> Guice direction + // ToDo -- Today this direction doesn't work without further work. Ignore the test for + // now. + @SuppressWarnings("unused") + @Ignore + @Test + public void testProvidesSupplierSpring() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + FooBarSpring.class); + SpringInjector injector = new SpringInjector(context); + Foo_Spring fooSpring = injector + .getInstance(Key.get(new TypeLiteral>() { + })).get(); + Bar_Spring barSpring = injector + .getInstance(Key.get(new TypeLiteral>() { + })).get(); + } - @Configuration - static class FooBarSpring { - @Bean - Supplier fooSpring() { - return ()->new Foo_Spring(); - } + @Configuration + static class FooBarSpring { + @Bean + Supplier fooSpring() { + return () -> new Foo_Spring(); + } - @Bean - Bar_Spring barSpring() { - return new Bar_Spring(); - } - } + @Bean + Bar_Spring barSpring() { + return new Bar_Spring(); + } + } - static class Foo_Spring { - } + static class Foo_Spring { + } - static class Bar_Spring { + static class Bar_Spring { - } + } }