需要引用AbstractModule中的Singleton的Guice依赖项

时间:2017-08-30 14:27:34

标签: scala dependency-injection playframework guice

我有一个外部库(scala-redis),在初始化客户端时需要隐式ActorSystem。我想在我的Play(2.6)应用程序中将我的RedisClient作为Singleton,因为将它作为Singleton是有意义的。

class CustomAppModule(environment: Environment,
                     configuration: Configuration) extends AbstractModule {
  def configure() = {
    //val system = getProvider(classOf[ActorSystem]).get()
    //val system = ActorSystem()
    //bind(classOf[ActorSystem]).toInstance(system)

    val redis = RedisClient(configuration.get[String]("redis.host"))(system)
    bind(classOf[RedisClient]).toInstance(redis)    
  }
}

第一个系统失败是因为“在创建Injector之前无法使用Provider”,第二个系统失败,因为Play Framework在应用程序启动时初始化ActorSystem本身,而第二个系统由于“绑定到akka.actor而失败”。 ActorSystem已在play.api.inject.BuiltinModule“。

配置

那么使用Guice / DI进行这种情况的惯用方法是什么?我是否需要一个将RedisClient作为值的包装器Singleton,以及可以注入ActorSystem的位置?

1 个答案:

答案 0 :(得分:1)

我认为提供方法可以解决您的问题。将模块写为

class MyModule extends AbstractModule {

   def configure() = {
   }

   @Provides
   @Singleton
   def givePrecious() : MyClass  = {
      new MyClass()
   }
}

这里我的班级看起来像

@Singleton 
class MyClass(a: String) {
   def this()  = {
      this("a")
      println("constructor called")
   }
}

现在我尝试创建此类的3个实例

val injector = Guice.createInjector(new MyModule())
val precious1 = injector.getInstance(classOf[MyClass])
val precious2 = injector.getInstance(classOf[MyClass])
val precious3 = injector.getInstance(classOf[MyClass])

您将看到字符串"构造函数名为"只打印一次。

为了简单起见,我制作了一个字符串。你可以尝试使它成为ActorSystem的一个实例。