Sono nuovo di questo concetto, ma qui è la mia comprensione.
Diciamo che avete interfacce A
e B
, e implementazioni Ai
e Bi
.
Se Ai
ha una dipendenza B
, e Bi
ha una dipendenza A
, allora Guice può creare un'implementazione procura di A
(lo chiamano Ap
) che ad un certo punto in futuro essere dato un Ai
di delegare al. Guice fornisce Ap
a Bi
per la sua dipendenza su A
, consentendo a Bi
di terminare l'istanziazione. Quindi, dal momento che Bi
è stato istanziato, Guice può creare un'istanza Ai
con Bi
. Quindi, dal momento che Ai
è ora buono da fare, Guice dice a Ap
di delegare a Ai
.
Se A
e B
non erano interfacce (e basta avuto Ai
e Bi
) questo proprio non sarebbe possibile, perché la creazione di Ap
richiederebbe di estendere la Ai
, che ha bisogno di un già Bi
.
Qui è quello che potrebbe essere simile con il codice:
classe
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() {
}
}
Il proxy che Guice fa sarebbe simile a questa:
public class Ap implements A {
private A delegate;
void setDelegate(A a) {
delegate = a;
}
public void doA() {
delegate.doA();
}
}
E tutto sarebbe cablata utilizzando questa idea di base:
Ap proxyA = new Ap();
B b = new B(proxyA);
A a = new A(b);
proxyA.setDelegate(a);
Ed ecco come sarebbe se avessi solo Ai
e Bi
, senza interfacce A
e B
.
public class Ap extends Ai {
private Ai delegate;
public Ap() {
super(_); //a B is required here, but we can't give one!
}
}
Se ho solo un tiro abbastanza classi dietro le interfacce, sarà tutto bene?
Direi che esistono restrizioni rigorose su come il proxy può essere interagito con il costruttore. In altre parole, se B prova a chiamare A prima che Guice abbia avuto la possibilità di popolare il proxy di A con la vera A, allora mi aspetterei una RuntimeException.
Anch'io preferisco questo approccio. Significa che non devi creare interfacce quando altrimenti non ne avresti bisogno. È anche più veloce/meno potenzialmente disordinato cambiare l'iniezione in un Provider piuttosto che creare interfacce. – specialtrevor
Che ne dici di avere una dipendenza esplicita da 'Guice' nel tuo codice app? Ho sempre pensato che fosse bello rimanere indipendenti dal framework DI. Prima di introdurre 'Provider' nel tuo codice potresti passare a dire' Spring' ma questo non è più possibile. –
Sto parlando di javax.inject.Provider, un'interfaccia standard JSR330. Non è richiesta alcuna dipendenza da guiz. –