Created
March 27, 2019 01:36
-
-
Save ryanhall07/e3eac6d2d47b72a4c37bce87219d7ced to your computer and use it in GitHub Desktop.
Guice Circular Dependency Issues
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import com.google.inject.AbstractModule; | |
| import com.google.inject.Guice; | |
| import com.google.inject.Injector; | |
| import java.util.Objects; | |
| import javax.inject.Inject; | |
| import javax.inject.Provider; | |
| import org.junit.jupiter.api.Test; | |
| import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; | |
| public class FooTest { | |
| /** | |
| * Guice can correctly detect the circular dependency when a Provider<Bar> is used in the | |
| * Foo Provider. This is because circular dependencies are only detected when attempting | |
| * to construct objects. | |
| */ | |
| @Test public void circularDependency() { | |
| AbstractModule module = new AbstractModule() { | |
| @Override protected void configure() { | |
| binder().disableCircularProxies(); | |
| bind(Foo.class).toProvider(new Provider<>() { | |
| @Inject Provider<Bar> bar; | |
| @Override public Foo get() { | |
| Objects.requireNonNull(bar.get()); | |
| return new Foo(); | |
| } | |
| }); | |
| } | |
| }; | |
| Injector injector = Guice.createInjector(module); | |
| assertThatThrownBy(() -> injector.getInstance(Foo.class)) | |
| .hasMessageContaining("Found a circular dependency"); | |
| assertThatThrownBy(() -> injector.getInstance(Bar.class)) | |
| .hasMessageContaining("Found a circular dependency"); | |
| } | |
| /** | |
| * Guice fails to detect the circular dependency and blows up building the Injector when | |
| * Bar is directly injected into the Foo Provider. This is because Guice is in the middle of | |
| * building the Injector. | |
| * | |
| * Is it an anti pattern to construct objects in a Provider? Should they always be Providers? | |
| */ | |
| @Test public void noCircularDependency() { | |
| AbstractModule module = new AbstractModule() { | |
| @Override protected void configure() { | |
| binder().disableCircularProxies(); | |
| bind(Foo.class).toProvider(new Provider<>() { | |
| @Inject Bar bar; | |
| @Override public Foo get() { | |
| Objects.requireNonNull(bar, "bar was never initialized by guice!"); | |
| return new Foo(); | |
| } | |
| }); | |
| } | |
| }; | |
| assertThatThrownBy(() -> Guice.createInjector(module)) | |
| .hasMessageContaining("bar was never initialized by guice!"); | |
| } | |
| static class Foo { | |
| } | |
| static class Bar { | |
| @Inject Foo foo; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment