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.
I'm new to this concept, but here's my understanding.
Let's say you have interfaces A
and B
, and implementations Ai
and Bi
.
If Ai
has a dependency on B
, and Bi
has a dependency on A
, then Guice can create a proxy implementation of A
(call it Ap
) that will at some point in the future be given an Ai
to delegate to. Guice gives that Ap
to Bi
for its dependency on A
, allowing Bi
to finish instantiation. Then, since Bi
has been instantiated, Guice can instantiate Ai
with Bi
. Then, since Ai
is now good to do, Guice tells Ap
to delegate to Ai
.
If A
and B
were not interfaces (and you just had Ai
and Bi
) this just would not be possible, because creating Ap
would require you to extend Ai
, which already needs a Bi
.
Here's what it might look like with code:
public interface A {
void doA();
}
public interface B {
void doB();
}
public class Ai implements A {
private final B b;
@Inject
public Ai(B b) {
this.b = b;
}
public void doA() {
b.doB();
}
}
public class Bi implements B {
private final A a;
@Inject
public Bi(A a) {
this.a = a;
}
public void doB() {
}
}
The proxy class that Guice makes would look like this:
public class Ap implements A {
private A delegate;
void setDelegate(A a) {
delegate = a;
}
public void doA() {
delegate.doA();
}
}
And it would all be wired using this basic idea:
Ap proxyA = new Ap();
B b = new B(proxyA);
A a = new A(b);
proxyA.setDelegate(a);
And here's what it would be like if you only had Ai
and Bi
, without interfaces A
and B
.
public class Ap extends Ai {
private Ai delegate;
public Ap() {
super(_); //a B is required here, but we can't give one!
}
}
If I just throw enough classes behind interfaces, will everything be fine?
I would guess that there are strict restrictions on how the proxy can be interacted with in the constructor. In other words, if B tries to call A before Guice has had a chance to populate A's proxy with the real A, then I would expect a RuntimeException.