如何在应用程序中访问 Play Framework 2.4 guice Injector?

How to access Play Framework 2.4 guice Injector in application?

我想在 Play Framework 2.4 中使用 Guice Injector class 的 getInstance 方法,如何访问它?

我使用 Guice FactoryModuleBuilder 实现了一个工厂,returns 另一个工厂在运行时!在返回工厂的第二级,我需要访问 Play Guice Injector 以使用反射而不是 @Inject 注释手动获取对象。

方法有很多种。我用这个。

编辑:这与 <= 2.4 的 Play 版本相关:

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

Play.current.injector.instanceOf[MyClass]

对于 >= 2.5 的版本:

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

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

最好注入Guice Injector:

@Inject
private Injector injector;

或者您可以将此代码用于 Play Framework Java 版本:

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

使用 Play Framework 2。5.x play.api.Play.current 已弃用,应始终首选 DI。因此,获取注入器实例的正确方法是使用:

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

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

即使使用 DI Provider class :)

也适用于我

除了其他 Play 2.5.x 解决方案之外,可能存在一种情况,您希望在不使用注入的情况下在对象中获取 Injector。例如,当您使用 Scala 单例时,@inject 可能无法正常工作。

在那种情况下,你可以使用这个:

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

object GlobalContext {
  private var injector: Injector = null  
}

用Guice模块设置单例为eager,否则不会自动初始化:

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

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

我真的很喜欢因为肯定有一些场景不能依赖构造函数注入来获取注入器本身,但是在Play 2中5.x你必须使用已弃用的play.api.Play.current.Injector 获取注入器实例的代码。

他的解决方案创建了对 Play 内置注入器的引用,并将其放入 Scala 对象中,任何组件都可以在需要时导入该对象。杰出的!

然而,为了使其工作,该对象需要提供一个 public 接口来获取注入器,所以这里是我修改后的代码来修复它并演示如何使用它。

# GolbalContext.scala

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

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

object GlobalContext {
  private var injectorRef: Injector = _

  def injector: Injector = injectorRef
}

初始化部分相同

# InjectionModule.scala

package modules

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

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

然后在 application.conf 中,确保 InjectionModule 是第一个启用的模块,以便后续模块可以正确使用注入器。

play.modules.enabled += "modules.InjectionModule"

并且客户端代码非常简单。在哪个组件中需要注入器:

// Import the object GlobalContext
import GlobalContext.injector

// ...
val yourClassInstance = injector.instanceOf[YourClass]