I am new to this concept, but here is my understanding.
Say you have interfaces A and B , as well as implementations of Ai and Bi .
If Ai has a dependency on B , and Bi has a dependency on A , then Guice can create an implementation of the proxy server A (let's call it Ap ), which will be provided at some point in the future by Ai for delegation. Guice gives Ap to Bi for his dependence on A , allowing Bi to complete the instance. Then, since Bi was created, Guice can create an instance of Ai using Bi . Then, since Ai now good at doing, Guice tells Ap delegate Ai .
If A and B were not interfaces (and you only had Ai and Bi ), this would simply not be possible, because creating Ap would require the extension Ai , which Bi already requires.
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 does will look like this:
public class Ap implements A { private A delegate; void setDelegate(A a) { delegate = a; } public void doA() { delegate.doA(); } }
And all this will be connected with this basic idea:
Ap proxyA = new Ap(); B b = new B(proxyA); A a = new A(b); proxyA.setDelegate(a);
And this is how it would be if you had only Ai and Bi , without interfaces A and B
public class Ap extends Ai { private Ai delegate; public Ap() { super(_);
If I just throw enough classes for interfaces, will everything be okay?
I would suggest that there are strict restrictions on how a proxy server can interact with a constructor. In other words, if B tries to call A before Guice has the opportunity to populate the proxy with real A, then I would expect a RuntimeException.