Guice-Proxy zur Unterstützung der zirkulären Abhängigkeit

8

Ich bekomme den folgenden Fehler in meinem Code beim Start:

  

Versucht, com.bar.Foo zu propagieren, um eine zirkuläre Abhängigkeit zu unterstützen, aber das ist es   keine Schnittstelle.

Wie funktioniert das Proxying genau? Wenn ich nur genug Klassen hinter die Schnittstellen werfe, wird alles gut?

(Ich weiß, dass zirkuläre Abhängigkeiten normalerweise ein Code-Geruch sind, aber ich denke in diesem Fall ist es in Ordnung.)

    
Nick Heiner 04.04.2012, 15:56
quelle

3 Antworten

7

Obwohl der Ansatz "inject a interface" absolut gültig ist und im Allgemeinen sogar die bessere Lösung sein kann, können Sie im Allgemeinen eine einfachere Lösung verwenden: Provider.

Für jede Klasse, die "A" verwalten kann, bietet guice auch " Provider<A> " an. Dies ist eine interne Implementierung der javax.inject.Provider-Schnittstelle, deren get() Nachricht " return injector.getInstance(A.class) " lautet. Sie müssen das Interface nicht selbst implementieren, es ist Teil der "Zaubermagie".

So können Sie das Beispiel A- & gt; B, B-A verkürzen zu:

%Vor%

Ich bevorzuge das, weil es lesbarer ist (Sie werden nicht getäuscht, um zu glauben, dass der Konstruktor bereits eine Instanz von "B" enthält) und da Sie die Provider selbst implementieren könnten, würde es immer "von Hand" funktionieren, außerhalb der Kontext (zum Beispiel zum Testen).

    
Jan Galinski 05.04.2012 05:36
quelle
6

Ich bin neu in diesem Konzept, aber hier ist mein Verständnis.

Nehmen wir an, Sie haben die Schnittstellen A und B und die Implementierungen Ai und Bi .

Wenn Ai eine Abhängigkeit von B hat und Bi eine Abhängigkeit von A hat, dann kann Guice eine Proxy-Implementierung von A (nennen Sie es Ap ) erstellen, die das irgendwann tun wird Zukünftig wird ein Ai an delegiert. Guice gibt das Ap an Bi für seine Abhängigkeit von A an, wodurch Bi die Instanziierung beenden kann. Dann, da Bi instanziiert wurde, kann Guice Ai mit Bi instanziieren. Dann, da Ai nun gut ist, teilt Guice Ap mit, dass er an Ai delegiert werden soll.

Wenn A und B keine Interfaces wären (und du hättest nur Ai und Bi gehabt), wäre dies einfach nicht möglich, weil das Erstellen von Ap es erfordern würde, dass du Ai erweitern würdest benötigt ein Bi .

So könnte es mit Code aussehen:

%Vor%

Die Proxy-Klasse, die Guice erstellt, würde folgendermaßen aussehen:

%Vor%

Und es wäre alles mit dieser Grundidee verkabelt:

%Vor%

Und so wäre es, wenn Sie nur Ai und Bi hätten, ohne die Schnittstellen A und B .

%Vor%
  

Wenn ich einfach genug Klassen hinter die Schnittstellen werfe, wird alles gut?

Ich würde vermuten, dass es strenge Einschränkungen gibt, wie mit dem Proxy im Konstruktor interagiert werden kann. Mit anderen Worten, wenn B versucht, A aufzurufen, bevor Guice die Chance hatte, den Proxy von A mit dem echten A zu füllen, würde ich eine RuntimeException erwarten.

    
Mark Peters 04.04.2012 16:02
quelle
2

Hier ist @ Jan-Galinskis Antwort, die in Scala erneuert wurde:

%Vor%     
Mike Slinn 09.08.2016 02:05
quelle