diff --git a/src/main/java/org/springframework/guice/annotation/GuiceFactoryBean.java b/src/main/java/org/springframework/guice/annotation/GuiceFactoryBean.java new file mode 100644 index 0000000..4ce5a78 --- /dev/null +++ b/src/main/java/org/springframework/guice/annotation/GuiceFactoryBean.java @@ -0,0 +1,30 @@ +package org.springframework.guice.annotation; + +import javax.inject.Provider; + +import org.springframework.beans.factory.FactoryBean; + +public class GuiceFactoryBean implements FactoryBean { + private final Provider provider; + private final Class beanType; + + public GuiceFactoryBean(Class beanType, Provider provider) { + this.provider = provider; + this.beanType = beanType; + } + + @Override + public T getObject() throws Exception { + return (T) provider.get(); + } + + @Override + public Class getObjectType() { + return beanType; + } + + @Override + public boolean isSingleton() { + return true; + } + } \ No newline at end of file diff --git a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java index 5e091db..7065cd5 100644 --- a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java +++ b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java @@ -14,18 +14,19 @@ package org.springframework.guice.annotation; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; import java.util.Map.Entry; -import javax.annotation.PostConstruct; - import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; @@ -36,52 +37,60 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; -import com.google.inject.Provider; @Configuration @Order(Ordered.HIGHEST_PRECEDENCE + 10) -public class ModuleRegistryConfiguration implements BeanPostProcessor { +public class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { - @Autowired - private DefaultListableBeanFactory beanFactory; - - @Autowired(required=false) - private List modules = Collections.emptyList(); + ApplicationContext applicationContext; - private Injector injector; - - @Bean - public Injector injector() { - return injector; + private Injector createInjector(Collection modules) { + return Guice.createInjector(modules); } - @PostConstruct - public void init() { - List modules = new ArrayList(this.modules); - modules.add(new SpringModule(beanFactory)); - injector = Guice.createInjector(modules); + private void mapBindings(Injector injector, BeanDefinitionRegistry registry) + { for (Entry, Binding> entry : injector.getBindings().entrySet()) { - if (entry.getKey().getTypeLiteral().getRawType().equals(Injector.class)) { + if (entry.getKey().getTypeLiteral().getRawType().equals(Injector.class) || + "spring-guice".equals(entry.getValue().getSource().toString())) { continue; } - final Provider provider = entry.getValue().getProvider(); - beanFactory.registerResolvableDependency(entry.getKey().getTypeLiteral().getRawType(), new ObjectFactory() { - @Override - public Object getObject() throws BeansException { - return provider.get(); - } - }); + + entry.getValue().getKey().toString(); + RootBeanDefinition bean = new RootBeanDefinition(GuiceFactoryBean.class); + ConstructorArgumentValues args = new ConstructorArgumentValues(); + args.addIndexedArgumentValue(0, entry.getKey().getTypeLiteral().getRawType()); + args.addIndexedArgumentValue(1, entry.getValue().getProvider()); + bean.setConstructorArgumentValues(args); + registry.registerBeanDefinition(entry.getValue().getKey().toString(), bean); } + + if(injector.getParent() != null) + { + mapBindings(injector.getParent(), registry); + } + + ((ConfigurableListableBeanFactory) registry).registerResolvableDependency(Injector.class, injector); + } + + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + + } @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + List modules = new ArrayList(((DefaultListableBeanFactory)registry).getBeansOfType(Module.class).values()); + modules.add(new SpringModule(this.applicationContext)); + Injector injector = createInjector(modules); + mapBindings(injector, registry); } @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext=applicationContext; } } \ No newline at end of file diff --git a/src/main/java/org/springframework/guice/module/SpringModule.java b/src/main/java/org/springframework/guice/module/SpringModule.java index 753ffd4..76ce070 100644 --- a/src/main/java/org/springframework/guice/module/SpringModule.java +++ b/src/main/java/org/springframework/guice/module/SpringModule.java @@ -85,7 +85,7 @@ public class SpringModule implements Module { if (type.getName().startsWith("com.google.inject")) { return; } - binder.bind(type).toProvider(provider); + binder.withSource("spring-guice").bind(type).toProvider(provider); bound.put(type, provider); } diff --git a/src/test/java/org/springframework/guice/SimpleWiringTests.java b/src/test/java/org/springframework/guice/SimpleWiringTests.java index 19126fe..6cb200c 100644 --- a/src/test/java/org/springframework/guice/SimpleWiringTests.java +++ b/src/test/java/org/springframework/guice/SimpleWiringTests.java @@ -37,7 +37,7 @@ public class SimpleWiringTests { assertNotNull(app.getInstance(Foo.class)); } - protected static class TestConfig extends AbstractModule { + public static class TestConfig extends AbstractModule { @Override protected void configure() { bind(Service.class).to(MyService.class); @@ -47,10 +47,10 @@ public class SimpleWiringTests { interface Service { } - protected static class MyService implements Service { + public static class MyService implements Service { } - protected static class Foo { + public static class Foo { @Inject public Foo(Service service) { diff --git a/src/test/java/org/springframework/guice/annotation/ModuleBeanWiringTests.java b/src/test/java/org/springframework/guice/annotation/ModuleBeanWiringTests.java index cb77c30..bf0449b 100644 --- a/src/test/java/org/springframework/guice/annotation/ModuleBeanWiringTests.java +++ b/src/test/java/org/springframework/guice/annotation/ModuleBeanWiringTests.java @@ -16,6 +16,7 @@ package org.springframework.guice.annotation; import static org.junit.Assert.assertNotNull; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -49,6 +50,9 @@ public class ModuleBeanWiringTests extends AbstractCompleteWiringTests { @EnableGuiceModules @Configuration public static class TestConfig extends AbstractModule { + + @Autowired Service service; + @Override protected void configure() { bind(Service.class).to(MyService.class);