diff --git a/README.md b/README.md index 4deec7e..ad4b7b5 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,12 @@ public static class TestConfig { The `Service` was defined in the Guice module `MyModule`, and then it was be bound to the autowired `spam()` method when Spring started. +### Filtering out modules from startup of ApplicationContext + +In certain cases you might need to ensure that some modules are not configured at all, even though they might not be present in the final `ApplicationContext`. +This might be due to external code that may be hard to change that cause side effects at binding time, or for other reasons. +To ensure this you can define a `ModuleFilter` bean that will be applied for filtering the list of modules in the Guice context before they are touched by the Spring-Guice bridge. This will ensure that no `configure()` methods are called on the filtered modules. + ## Configuration Class Enhancements Note that the `Module` bean definition in the example above is diff --git a/src/main/java/org/springframework/guice/annotation/ModuleFilter.java b/src/main/java/org/springframework/guice/annotation/ModuleFilter.java new file mode 100644 index 0000000..f65428b --- /dev/null +++ b/src/main/java/org/springframework/guice/annotation/ModuleFilter.java @@ -0,0 +1,10 @@ +package org.springframework.guice.annotation; + +import com.google.inject.Module; + +@FunctionalInterface +public interface ModuleFilter { + + boolean filter(Module module); + +} diff --git a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java index 329deb1..3ff4d4b 100644 --- a/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java +++ b/src/main/java/org/springframework/guice/annotation/ModuleRegistryConfiguration.java @@ -125,8 +125,18 @@ class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + + Map moduleFilters = ((ConfigurableListableBeanFactory) registry) + .getBeansOfType(ModuleFilter.class); + if (moduleFilters.size() > 1) { + throw new IllegalStateException( + "You can only define zero or one ModuleFilter implementation. Implementations found: " + + String.join(",", moduleFilters.keySet())); + } + ModuleFilter moduleFilter = moduleFilters.values().stream().findFirst().orElse(module -> true); List modules = new ArrayList<>( - ((ConfigurableListableBeanFactory) registry).getBeansOfType(Module.class).values()); + ((ConfigurableListableBeanFactory) registry).getBeansOfType(Module.class).values()).stream() + .filter(moduleFilter::filter).collect(Collectors.toList()); SpringModule module = new SpringModule((ConfigurableListableBeanFactory) registry, this.enableJustInTimeBinding); modules.add(module); diff --git a/src/test/java/org/springframework/guice/annotation/EnableGuiceModulesTests.java b/src/test/java/org/springframework/guice/annotation/EnableGuiceModulesTests.java index 9379ea1..d04a5b9 100644 --- a/src/test/java/org/springframework/guice/annotation/EnableGuiceModulesTests.java +++ b/src/test/java/org/springframework/guice/annotation/EnableGuiceModulesTests.java @@ -75,6 +75,14 @@ public class EnableGuiceModulesTests { context.close(); } + @Test + public void moduleBeanFiltersOutModules() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + FilteringModuleBeanConfig.class); + assertThat(context.getBean(Foo.class)).isNotNull(); + context.close(); + } + @Test public void testInjectorCreationDoesNotCauseCircularDependencyError() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class); @@ -151,6 +159,32 @@ public class EnableGuiceModulesTests { } + @Configuration(proxyBeanMethods = false) + @EnableGuiceModules + protected static class FilteringModuleBeanConfig { + + @Bean + public static MyModule2 module2() { + return new MyModule2(); + } + + @Bean + public static MyModule module() { + return new MyModule(); + } + + @Bean + public Foo service(Service service) { + return new Foo(service); + } + + @Bean + ModuleFilter moduleFilter() { + return module -> !(module instanceof MyModule2); + } + + } + protected static class MyModule extends AbstractModule { @Override @@ -160,6 +194,15 @@ public class EnableGuiceModulesTests { } + protected static class MyModule2 extends AbstractModule { + + @Override + protected void configure() { + throw new RuntimeException("This should not be called when filtered out!"); + } + + } + public static class SpringProvidedBean { public SpringProvidedBean(GuiceProvidedBean guiceProvidedBean) {