diff --git a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java index 9e3e964..4537704 100644 --- a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java +++ b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java @@ -19,6 +19,7 @@ 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; @@ -35,6 +36,7 @@ import com.google.inject.spi.PrivateElements; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +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; @@ -43,8 +45,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextException; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; @@ -60,13 +60,13 @@ import org.springframework.guice.module.SpringModule; */ @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) -class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor, - ApplicationContextAware, ApplicationListener { +class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { private static final String SPRING_GUICE_DEDUPE_BINDINGS_PROPERTY_NAME = "spring.guice.dedup"; private ApplicationContext applicationContext; private List modules; private ConfigurableListableBeanFactory beanFactory; + private AtomicBoolean injectorCreated = new AtomicBoolean(false); private void createInjector(List modules, ConfigurableListableBeanFactory beanFactory) { @@ -156,11 +156,6 @@ class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor } } mapBindings(bindings, registry); - - // This event can be published now and it wont actually be processed until later - // (during onRefresh()). There's no other way to get a hook into this phase of the - // lifecycle. - applicationContext.publishEvent(new CreateInjectorSignalEvent()); } private void extractPrivateElements(Map, Binding> bindings, @@ -237,6 +232,20 @@ class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; + beanFactory.registerSingleton("guiceInjectorInitializer", new GuiceInjectorInitializingBeanPostProcessor(){ + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if(injectorCreated.compareAndSet(false,true)) { + createInjector(modules, beanFactory); + } + return bean; + } + }); } @Override @@ -244,21 +253,14 @@ class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor throws BeansException { this.applicationContext = applicationContext; } - - @Override - public void onApplicationEvent(CreateInjectorSignalEvent event) { - createInjector(modules, beanFactory); + + private static class GuiceInjectorInitializingBeanPostProcessor implements BeanPostProcessor, Ordered { + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 1; + } } } -/** - * Signaling event used to trigger injector creation after BeanPostProcessors have been - * applied. - */ -class CreateInjectorSignalEvent extends ApplicationEvent { - private static final long serialVersionUID = -6546970378679850504L; - public CreateInjectorSignalEvent() { - super(serialVersionUID); - } -} + diff --git a/src/test/java/org/springframework/guice/BeanPostProcessorTests.java b/src/test/java/org/springframework/guice/BeanPostProcessorTests.java index b758733..e606523 100644 --- a/src/test/java/org/springframework/guice/BeanPostProcessorTests.java +++ b/src/test/java/org/springframework/guice/BeanPostProcessorTests.java @@ -7,9 +7,14 @@ import javax.inject.Inject; import org.junit.Test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; import org.springframework.guice.BeanPostProcessorTests.GuiceBeanThatWantsPostProcessedBean; import org.springframework.guice.BeanPostProcessorTests.GuiceBeanThatWantsSpringBean; import org.springframework.guice.BeanPostProcessorTests.PostProcessedBean; @@ -69,22 +74,42 @@ public class BeanPostProcessorTests { @EnableGuiceModules @Configuration class BeanPostProcessorTestConfig { + + public static class PostProcessorRegistrar implements BeanDefinitionRegistryPostProcessor { + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + BeanDefinitionBuilder bean = BeanDefinitionBuilder.genericBeanDefinition(TestBeanPostProcessor.class); + registry.registerBeanDefinition("postProcessor", bean.getBeanDefinition()); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {} + + } + + public static class TestBeanPostProcessor implements BeanPostProcessor, Ordered { + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if(bean instanceof PostProcessedBean) { + ((PostProcessedBean)bean).postProcessed = true; + } + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public int getOrder() { + return 0; + } + } + @Bean - public BeanPostProcessor postProcessor() { - return new BeanPostProcessor() { - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if(bean instanceof PostProcessedBean) { - ((PostProcessedBean)bean).postProcessed = true; - } - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - }; + public PostProcessorRegistrar postProcessorRegistrar() { + return new PostProcessorRegistrar(); } @Bean diff --git a/src/test/java/org/springframework/guice/BindingDeduplicationTests.java b/src/test/java/org/springframework/guice/BindingDeduplicationTests.java index 4c97722..22aaf38 100644 --- a/src/test/java/org/springframework/guice/BindingDeduplicationTests.java +++ b/src/test/java/org/springframework/guice/BindingDeduplicationTests.java @@ -1,12 +1,11 @@ package org.springframework.guice; import com.google.inject.AbstractModule; -import com.google.inject.CreationException; import com.google.inject.Module; import org.junit.AfterClass; import org.junit.Test; - +import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,7 +31,7 @@ public class BindingDeduplicationTests { context.close(); } - @Test(expected = CreationException.class) + @Test(expected = BeanCreationException.class) public void verifyDuplicateBindingErrorWhenDedupeNotEnabled() { System.setProperty("spring.guice.dedup", "false"); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( diff --git a/src/test/java/org/springframework/guice/InjectorFactoryTests.java b/src/test/java/org/springframework/guice/InjectorFactoryTests.java index ca7ba2c..8c12392 100644 --- a/src/test/java/org/springframework/guice/InjectorFactoryTests.java +++ b/src/test/java/org/springframework/guice/InjectorFactoryTests.java @@ -3,7 +3,7 @@ package org.springframework.guice; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.context.ApplicationContextException; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -31,7 +31,7 @@ public class InjectorFactoryTests { context.close(); } - @Test(expected = ApplicationContextException.class) + @Test(expected = BeanCreationException.class) public void testMultipleInjectorFactoriesThrowsApplicationContextException() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(InjectorFactoryConfig.class, SecondInjectorFactoryConfig.class, ModulesConfig.class);