Java 如何在应用程序中访问PlayFramework2.4Guice注入器?

Java 如何在应用程序中访问PlayFramework2.4Guice注入器?,java,scala,playframework,playframework-2.0,guice,Java,Scala,Playframework,Playframework 2.0,Guice,我想使用PlayFramework2.4中GuiceInjector类的getInstance方法,如何访问它 我使用GuiceFactoryModuleBuilder实现了一个在运行时返回另一个工厂的工厂!在返回工厂的第二级,我需要访问Play Guice Injector,以使用反射而不是@Injection注释手动获取对象。有很多方法。我用这个 编辑:这与=2.5的播放版本相关: 导入play.api.inject.Injector 导入javax.inject.inject 类MySer

我想使用PlayFramework2.4中Guice
Injector
类的
getInstance
方法,如何访问它


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

有很多方法。我用这个

编辑:这与=2.5的播放版本相关:

导入play.api.inject.Injector
导入javax.inject.inject
类MyService@Inject()(注入器:注入器)={
val myClassInstance=injector.instanceOf[MyClass]
//做事
}

最好注入Guice注射器:

@Inject
private Injector injector;
或者,您可以在Play Framework Java edition中使用以下代码:

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类执行此操作时对我也有效:)

除了其他Play 2.5.x解决方案之外,可能存在一种情况,即您希望在对象中获得注入器而不使用注入器。例如,当您使用Scala单例时,@inject可能不起作用

在这种情况下,您可以使用:

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

object GlobalContext {
  private var injector: Injector = null  
}
使用Guice模块将singleton设置为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对象中,任何组件都可以在需要时导入该对象。太棒了

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

# 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]

虽然技术上是正确的,但如果静态访问喷油器(在生产系统中),第一种方法将导致错误的情况。当然,这种情况不应该发生,但第二种方法至少会很清楚。如果希望具有不同的绑定,则应在开发环境中使用另一个应用程序加载程序。Play.current与所有其他静态帐户一样不推荐使用。必须使用DI而不是旧的静态方法。第一种方法是如何工作的?这个应用程序是如何创建的?我试图在Play 2.3应用程序中引入Guice注入,其中注入程序在Global.scala中定义?这是可行的,但是如果没有@Inject符号,我无法找到一个合适的方法来访问注入器。@Serendipity您可以根据Devabc的解决方案来检查我对这个问题的答案。虽然这个问题是关于Guice注入器的,但公认的答案是关于Play injector,这是一个不同的类。您能在这里详细说明一下吗?为什么需要访问注入器?@marcospereira我使用Guice FactoryModuleBuilder实现了一个工厂,该工厂在运行时返回另一个工厂!在返回工厂的第二个级别中,我需要访问Play guice Injector,以使用反射而不是注入注释手动获取对象。我这样做是因为您应该避免使用
Play.current
,因为它将在某个点被删除。也许你可以注射注射器?@marcospereira我怎样才能注射注射器?我认为这是一个更好的解决办法。谢谢,跟其他的一样。请看这里的示例(Java):在我的Java中,这种类型的注入不起作用。有什么想法吗?@SimonFakir在Java中你应该注入play.inject.Injector,因为play.api.*下的所有内容都是针对Scala的。@Egregore,我认为你的答案应该被接受!另外,如果您还包括必须注入play.Injector.Injector的Java示例,那就太好了。当您在早期阶段,即在注入器初始化之前需要注入器时,这种方法可能会失败(我现在面临这个问题)@ZéByte它应该通过放置
bind(classOf[GlobalContext])。asEagerSingleton()
作为模块的第一行,
play.modules.enabled+=“modules.InjectionModule”
作为第一个启用的模块。因为它将是最早的模块,之后的任何模块都可以访问它。即使您作为渴望的单例绑定,也不能保证在您尝试使用它时注入器可用