Guice eifrige / faule Singleton Instanziierungen

8

Ich habe Probleme, zu verstehen, wie Guices Singleton-Instanziierungen funktionieren. Ich habe die verfügbare Dokumentation gelesen (hier - Ссылка ), aber ich kann es immer noch nicht verstehen einige Dinge aus:

1) Ich habe Guice mit Tomcat integriert und einige Bindings in einem ServletModule eingerichtet:

%Vor%

(wo die MyOtherServlet-Klasse darüber eine @ Singleton-Anmerkung hat) Meine Absicht war, zwei Servlets zu haben, von denen einer eifrig instanziiert wird, während der andere nicht. Es scheint jedoch so, als ob die Zeile "serve ... with ..." Servlets-Objekte automatisch instanziiert, obwohl diese Klasse nicht als eifriger Singleton gebunden ist. Der Link, den ich oben angehängt habe, erwähnt den Unterschied zwischen Guice, der unter Stage.Development und Stage.Production läuft - allerdings geschah dies auch, als ich explizit Stage.Development verwendete (was ohnehin der Standard ist). Gibt es eine Möglichkeit, dies zu vermeiden?

2) (fortfahren 1) Um sicherzustellen, dass MyServlet zuerst instanziiert wird, obwohl alle Servlets sofort instanziiert werden, habe ich beim Erstellen eines Injektors die Reihenfolge der Module (und der Bindungsanweisungen) geändert, sodass die Bindung für MyServlet angezeigt wird zuerst. Ich stellte jedoch fest, dass es immer noch später instanziiert wird als einige andere Bindungen (von Nicht-Servlet-Klassen), die folgende Form hatten:

%Vor%

, obwohl diese anderen Bindungen später in der Reihenfolge der Module / Bindings erschienen. Ich habe es untersucht und festgestellt, dass Guice einfach eifrige Singletons instanziiert, die an die Form von "bind ... an ... asEagerSingleton ()" gebunden waren, bevor es "bind ... asEagerSingleton ()" verwendet, und so habe ich es gelöst, indem ich die Zeile geändert habe:     bind (MyServlet.class) .asEagerSingleton (); in:     bind (MyServletDummyInterface.class) .to (MyServlet.class) .asEagerSingleton ()

und das hat wirklich funktioniert. Dennoch würde ich lieber vermeiden, eine Dummy-Schnittstelle zu haben, nur um das zu lösen, also habe ich mich gefragt, ob jemand eine bessere Lösung dafür hatte ..?

3) Ich habe zwei Guice-Module - ein ServletModule und ein AbstractModule. Das ServletModule configureServlets () enthält die folgende Bindung:

%Vor%

configure () des AbstractModuls hat die folgenden Bindungen:

%Vor%

Zusätzlich hat die SomeServlet-Klasse ein injiziertes Feld vom Typ SomeInterface und eine @ Singleton-Annotation über der Klasse.

Nun würde man erwarten, dass beim Erzeugen eines Injektors die SomeImpl-Klasse instanziiert wird und dieselbe Instanz in die SomeServlet-Instanz injiziert wird. Wie bereits erwähnt, scheinen Servlets, die mit einer Anweisung "serve ... with ..." verbunden sind, auch eifrig instanziiert zu werden, aber in jedem Fall sollte nur ein SomeImpl-Objekt instanziiert sein. Aus irgendeinem Grund habe ich jedoch zwei SomeImpl-Objekte instanziiert. Um es zu umgehen, mischte ich die beiden Zeilen in configure () ein bisschen, und anstelle des oben genannten hatte ich dort die folgenden Zeilen:

%Vor%

und dann hat es gut funktioniert, und ich habe nur eine Instanz von SomeImpl instanziiert. Ich verstehe nicht wirklich, warum der Schalter wichtig sein sollte - ich kann sehen, wie der letztere Weg "besser" ist, aber ich würde erwarten, dass beide richtig funktionieren, also frage ich mich, ob ich hier etwas falsch mache. ?



Sorry über die Länge,
Danke für die Hilfe!

    
user976850 08.11.2011, 16:12
quelle

1 Antwort

7

1) Es gibt keine Möglichkeit, dies zu vermeiden, da Guice die init() -Methode aller Servlets bei der Initialisierung ihrer eigenen Filterpipeline aufruft und sie somit alle konstruiert. Wenn Sie eine solche Logik für die verzögerte Initialisierung wirklich benötigen, sollten Sie sie in das Servlet selbst einfügen (oder eine entkoppelte Hilfsklasse verwenden, oder ... je nach Anwendungsfall gibt es viele Möglichkeiten).

2) Allgemein gesagt, die Module von Guice deklarieren Bindings , es sind keine Bootstrap-Definitionen mit genauen Instanziierungsreihenfolgen vorgesehen. Wenn Sie eine solche definierte Instanziierungsreihenfolge benötigen, erstellen Sie die Objekte selbst in der gewünschten Reihenfolge und binden Sie sie über bind(...).toInstance(...) . Wenn Sie eine Injektion in den selbst konstruierten Instanzen benötigen, können Sie requestInjection(...) verwenden (wenn Feld / Methode-Injektion ausreichend ist, ist es für die Konstruktorinjektion mühsamer).

3) Der Geltungsbereich von Guice bezieht sich auf den verbindlichen Schlüssel, nicht auf den verbindlichen Wert Geltungsbereich anwenden beschreibt, warum nur das zweite Beispiel wie vorgesehen funktioniert.

    
Heri 08.11.2011, 22:58
quelle

Tags und Links