2011-11-08 33 views
8

Mam pewne problemy ze zrozumieniem, jak działa pojedyncza instancja Guice. Czytałem dostępną dokumentację (tutaj - http://code.google.com/p/google-guice/wiki/Scopes), ale nadal nie mogę wymyślić niektórych rzeczy:Guice chętnych/leniwe instynkty singletonowe

1) Zintegrowaliśmy Guice z Tomcat, a także skonfigurowałem kilka powiązań w ServletModule:

bind(MyServlet.class).asEagerSingleton(); 
serve("myUrl").with(MyServlet.class); 
serve("myOtherUrl").with(MyOtherServlet.class); 

(gdzie klasa MyOtherServlet ma adnotacji @Singleton nad nim) Moim zamiarem było tu dwa serwletów, gdzie jeden jest chętnie instancji, podczas gdy inne nie. Jednak wygląda na to, że linia "serve ... with ..." automatycznie tworzy instancje obiektów serwletów, mimo że ta klasa nie jest związana jako gotowy singleton. Powyższy link wspomina o różnicy między Guice działającym w fazie Stage.Development a Stage.Production - jednak to się zdarzyło, nawet gdy wyraźnie użyłem Stage.Development (który jest domyślnie any). Czy można tego uniknąć?

2) (kontynuuje 1) Próbując upewnić się, że MyServlet zostanie najpierw utworzony, mimo że wszystkie serwlety aktualnie tworzą instancję, zmieniłem kolejność modułów (i instrukcji wiążących) podczas tworzenia wtryskiwacza, tak aby wiązanie dla MyServlet pojawia się jako pierwszy. Uważam jednak, że to wciąż dostaje instancja później niż w niektórych innych wiązań (klas non-serwletów), które zostały w postaci:

bind(MyInterface.class).to(MyClass.class).asEagerSingleton() 

chociaż te inne powiązania później pojawił się w modules/wiązaniami kolejności. Zajrzałem do tego i odkryłem, że Guice po prostu tworzy przypadki chętnych singletonów, które były związane formą "bind ... to ... asEagerSingleton()" zanim zrobi to z "bind ... asEagerSingleton()" , a więc rozwiązałem go, modyfikując linię: bind (MyServlet.class) .asEagerSingleton(); do: bind (MyServletDummyInterface.class) .to (MyServlet.class) .asEagerSingleton()

i to faktycznie zadziałało. Mimo to, wolałbym uniknąć interfejsu manekina tylko po to, aby rozwiązać ten problem, więc zastanawiałem się, czy ktoś miał lepsze rozwiązanie tego ...?

3) Mam dwa moduły Guice - jeden ServletModule i jeden AbstractModule. W configureServlets ServletModule() ma następujący wiązanie w tym:

serve("aUrl").with(SomeServlet.class); 

może skonfigurować AbstractModule w() ma następujące wiązania:

bind(SomeImpl.class).asEagerSingleton(); 
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class); 

Dodatkowo Klasa SomeServlet ma wtryskiwanego pole typu SomeInterface, i ma adnotację @Singleton na górze klasy.

Można się spodziewać, że po utworzeniu iniektora zostanie utworzona klasa SomeImpl, a to samo wystąpienie zostanie wprowadzone do instancji SomeServlet. Jak już wcześniej wspomniano, serwlety powiązane z instrukcją "serve ... with ..." również wydają się być chętnie tworzone, ale tak czy inaczej powinien istnieć tylko jeden instancjonowany obiekt SomeImpl. Jednak z jakiegoś powodu, podczas wykonywania tej czynności otrzymałem dwa obiekty SomeImpl. Aby obejść to, że miesza się dwie linie w configure() trochę, a zamiast powyższego miałem tam następujące linie:

bind(SomeImpl.class).in(Singleton.class) 
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton(); 

a następnie pracował w porządku, i mam tylko jedno wystąpienie Utworzono SomeImpl.Naprawdę nie rozumiem, dlaczego przełącznik ma znaczenie - widzę, jak ten drugi sposób jest "lepszy", ale spodziewałbym się, że oba będą działać poprawnie, więc zastanawiam się, czy coś tu nie gra ... ?



Niestety o długości
Dzięki za pomoc!

Odpowiedz

7

1) Nie można tego uniknąć, ponieważ Guice wywołuje metodę init() dla wszystkich serwletów podczas inicjalizacji własnego potoku filtru, a zatem konstruuje je wszystkie. Jeśli naprawdę potrzebujesz takiej leniwej logiki inicjalizacji, powinieneś umieścić ją w samym serwlecie (lub użyć oddzielonej klasy pomocnika lub ... istnieje wiele sposobów, w zależności od twojego przypadku użycia).

2) Ogólnie rzecz biorąc, moduły Guice deklarują wiązania, nie są zaprojektowane jako definicje bootstrap z dokładnymi kolejnymi zleceniami. Jeśli potrzebujesz tak zdefiniowanej kolejności tworzenia instancji, utwórz obiekty samodzielnie w żądanej kolejności i związaj je poprzez bind(...).toInstance(...). Jeśli potrzebujesz iniekcji we własnych instancjach, możesz użyć requestInjection(...) (jeśli wstrzyknięcie pola/metody jest wystarczające, jest bardziej uciążliwe dla wstrzyknięcia konstruktora).

3) Zakres Guice dotyczy klucza wiążącego, a nie wartości wiązania, Applying Scopes opisuje, dlaczego tylko drugi przykład działa zgodnie z przeznaczeniem.