2016-01-19 16 views
6

Chcę użyć metody getInstance klasy Guice Injector w Play Framework 2.4, w jaki sposób mogę uzyskać do niej dostęp?Jak uzyskać dostęp do aplikacji Play Framework 2.4 guice Injector w aplikacji?

Użyłem Guice FactoryModuleBuilder do wdrożenia fabryki, która zwraca inną fabrykę w czasie pracy! Na drugim poziomie zwracania fabryki muszę uzyskać dostęp do Guice Injector Play, aby ręcznie pobrać obiekty za pomocą odbicia zamiast adnotacji @Inject.

+0

Czy mógłbyś jeszcze bardziej rozwinąć tutaj? Dlaczego potrzebujesz dostępu do wtryskiwacza? – marcospereira

+0

@marcospereira Użyłem Guice FactoryModuleBuilder do wdrożenia fabryki, która zwraca inną fabrykę w czasie pracy! na drugim poziomie powracającej fabryki muszę uzyskać dostęp do Play guice Injector, aby ręcznie pobrać obiekty za pomocą odbicia zamiast innotacji Inject. –

+0

Pytam, ponieważ powinieneś unikać używania 'Play.current', ponieważ zostanie on w pewnym momencie usunięty. Może możesz wstrzyknąć wtryskiwacz? – marcospereira

Odpowiedz

12

Istnieje wiele sposobów. Używam tego.

Edit: Jest to istotne dla wersji gry, który są < = 2.4:

Play.maybeApplication.map(_.injector.instanceOf[MyProdClass]).getOrElse(new MyDevClass) 

lub

Play.current.injector.instanceOf[MyClass] 

Dla wersji, które są> = 2,5:

import play.api.inject.Injector 
import javax.inject.Inject 

class MyService @Inject() (injector: Injector) ={ 
    val myClassInstance = injector.instanceOf[MyClass] 
    //do stuff 
} 
+0

Chociaż technicznie poprawne, pierwsze podejście doprowadziłoby do niewłaściwej instancji, gdyby do Injectora dostęp był statyczny (w systemie produktywnym). To nie powinno się zdarzyć - oczywiście, ale drugie podejście byłoby przynajmniej jasne. Powinieneś użyć innego programu ładującego aplikacje w środowisku deweloperów, jeśli chcesz mieć różne powiązania. – rethab

+1

Play.current jest przestarzałe, podobnie jak wszystkie inne elementy statyczne. DI musi być użyty zamiast starego statycznego podejścia. – Serg

+0

Jak działa pierwsze podejście? W jaki sposób tworzona jest ta aplikacja? Próbuję wprowadzić Guice Injection w aplikacji Play 2.3, gdzie wtryskiwacz jest zdefiniowany wewnątrz Global.scala? To działa, ale nie mogę znaleźć porządnego sposobu dostępu do wtryskiwacza bez notacji @Inject w innym miejscu. – Serendipity

4

Jest lepiej wstrzykiwać Guice Injector:

@Inject 
private Injector injector; 

Albo można użyć tego kodu do gry edycji Framework Java:

Play.application().injector().instanceOf(YourClass.class); 
5

z luzem ramowego 2.5.x play.api.Play.current jest przestarzała i DI zawsze powinny być preferowane. Dlatego właściwym sposobem na uzyskanie instancji wtryskiwacza jest za pomocą:

import play.api.inject.Injector 
import javax.inject.Inject 

class SomeClassRequiringInjector @Inject() (injector: Injector) { ... } 

pracuje dla mnie, nawet jeśli robi to z klasą Provider DI :)

+1

w moim Java tego typu wstrzykiwanie nie działa. Dowolny pomysł? –

+1

@SimonFakir w Javie powinieneś wstrzyknąć play.inject.Injector, ponieważ wszystko pod play.api. * Jest dla Scala. – Serg

+0

@Eregregore, myślę, że twoja odpowiedź powinna zostać przyjęta! Byłoby miło, gdybyś również dodał przykład Java, do którego należy wstrzyknąć play.inject.Injector. – Serg

3

Oprócz innych rozwiązań play 2.5.x, nie może być sytuacji, w którym chcesz uzyskać wtryskiwacz w obiekcie bez użycia wtrysku. Na przykład, gdy używasz singletu Scala, dla którego @inject prawdopodobnie nie działa.

W tym przypadku można użyć tego:

@Singleton 
class GlobalContext @Inject()(injector: Injector) { 
    GlobalContext.injector = injector 
} 

object GlobalContext { 
    private var injector: Injector = null 
} 

Z modułem Guice ustawić singleton do chętni, w przeciwnym razie nie zostanie zainicjowana automatycznie:

// Module.scala 
class Module extends AbstractModule { 
    override def configure() = { 
    // ... 

    // Eager initialize Context singleton 
    bind(classOf[GlobalContext]).asEagerSingleton() 
    } 
} 
0

naprawdę lubię Devabc's solution ponieważ istnieją pewne scenariusze, które nie mogą polegać na iniekcji konstruktora, aby uzyskać sam wtryskiwacz, zamiast tego w wersji 2.5.x należy użyć wycofanego kodu play.api.Play.current.Injector, aby uzyskać wtryskiwacz.

Jego rozwiązanie tworzy odniesienie do wbudowanego wtryskiwacza Play i umieszcza go w obiekcie Scala, który może zostać zaimportowany przez dowolny komponent, gdy zajdzie taka potrzeba. Znakomity!

Aby to działało, obiekt musi jednak udostępnić interfejs publiczny, aby uzyskać wtryskiwacz, więc oto mój poprawiony kod, aby go naprawić i pokazać, jak można go użyć.

import play.api.inject.Injector 
import javax.inject.Inject 

@Singleton 
class GlobalContext @Inject()(playInjector: Injector) { 
    GlobalContext.injectorRef = playInjector 
} 

object GlobalContext { 
    private var injectorRef: Injector = _ 

    def injector: Injector = injectorRef 
} 

Część inicjalizacyjna jest taka sama.

// InjectionModule.scala 
package modules 

class InjectionModule extends AbstractModule { 
    override def configure() = { 
    // ... 

    // Eager initialize Context singleton 
    bind(classOf[GlobalContext]).asEagerSingleton() 
    } 
} 

// application.conf 
play.modules.enabled += "modules.InjectionModule" 

Kod klienta jest bardzo prosty. W zależności od tego, który komponent wymaga wtryskiwacza:

Powiązane problemy