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.)
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).
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
.
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.
Hier ist @ Jan-Galinskis Antwort, die in Scala erneuert wurde:
%Vor%Tags und Links java dependency-injection guice