Guice proxying to support circular dependency
dependency-injection, guice, java
Solution
While the "inject an interface" approach is totally valid, and might even be the better solution in some occasions, in general, you can use a simpler solution: Providers.
For every class "A" guice can manage, guice also offers a "`Provider<A>`". This is an internal implementation of the javax.inject.Provider-interface, whose `get()` message will "`return injector.getInstance(A.class)`". You dont have to implement the Interface yourself, its part of the "guice magic".
Thus you can shorten the A->B, B-A example to:
public class CircularDepTest {
static class A {
private final Provider<B> b;
private String name = "A";
@Inject
public A(Provider<B> b) {
this.b = b;
}
}
static class B {
private final Provider<A> a;
private String name = "B";
@Inject
public B(Provider<A> a) {
this.a = a;
}
}
@Inject
A a;
@Inject
B b;
@Before
public void setUp() {
Guice.createInjector().injectMembers(this);
}
@Test
public void testCircularInjection() throws Exception {
assertEquals("A", a.name);
assertEquals("B", a.b.get().name);
assertEquals("B", b.name);
assertEquals("A", b.a.get().name);
}}
I prefer this, because its more readable (you are not fooled to beleive that the constructor already holds an instance of "B") and since you could implement the Providers yourself, it would still work "by Hand", outside the guice context (for testing for example).
Problem
I'm getting the following error in my code at launch: Tried proxying com.bar.Foo to support a circular dependency, but it is not an interface. How exactly does this proxying work? If I just throw enough classes behind interfaces, will everything be fine? (I know that circular dependencies are usually a code smell, but I think in this case it's ok.)