Scala Play Framework 2.5.x:在模块中注入环境

Scala Play Framework 2.5.x:在模块中注入环境,scala,dependency-injection,guice,playframework-2.5,Scala,Dependency Injection,Guice,Playframework 2.5,Play app包含一个自定义模块,可在应用程序启动期间初始化DB/表格。 从v2.5.x开始,应用程序模式(prod、test、dev)需要注入,而不是使用Current。我试图在模块代码中应用以下注入参数,但发现编译错误 trait MyInit[Environment] { val env: Environment } class MyInitClass[Environment] @Inject() ( val env: Environment ) extends MyInit[

Play app包含一个自定义模块,可在应用程序启动期间初始化DB/表格。 从v2.5.x开始,应用程序模式(prod、test、dev)需要注入,而不是使用Current。我试图在模块代码中应用以下注入参数,但发现编译错误

trait MyInit[Environment] {
  val env: Environment
}

class MyInitClass[Environment] @Inject() (
  val env: Environment
) extends MyInit[Environment] {
  initializeDB()

  def initializeDB() = {
    Logger.info("MyINIT: Creating database...")
    MyDBService.createDatabase()
    Logger.info("MyINIT: Creating tables...")
    MyDBService.createTables()
  }
}

class MyModule(environment: Environment,
             configuration: Configuration) extends AbstractModule with ScalaModule {
  def configure() = {
    bind[MyInit[Environment]].to[MyInitClass[Environment]].asEagerSingleton()
  }
}

在Play 2.5.x(Scala)中的模块初始化过程中,是否有一种指定的查找环境/模式的方法?

我将重写您的代码,以消除可能出现的小混乱。这正是您的代码,只需对类型参数进行少量重命名:

import javax.inject.Inject
import play.api.Logger
import play.api.Environment
import play.api.Configuration
import com.google.inject.AbstractModule

trait MyInit[T] {
  val env: T
}

class MyInitClass[T] @Inject() (val env: T) extends MyInit[T] {
  initializeDB()

  def initializeDB() = {
    Logger.info("MyINIT: Creating database...")
    MyDBService.createDatabase()
    Logger.info("MyINIT: Creating tables...")
    MyDBService.createTables()
  }
}
我重命名了类型参数,以避免与
play.api.Environment
混淆。我感觉这不是您想要的,因为
MyInitClass
在任何地方都不会主动接收
play.api.Environment

如果您想进行一些初始化,为什么不做一些更简单、更直接的操作呢

import com.google.inject.AbstractModule
import play.api.{Configuration, Environment, Mode}

class DatabaseInitializerModule(
  environment: Environment,
  configuration: Configuration
) extends AbstractModule {

  def configure() = {
    environment.mode match {
      case Mode.Dev =>
        // Start dev database
      case Mode.Test =>
        // Start test database
      case Mode.Prod =>
        // Start prod database
    }
  }
}
import javax.inject.Inject

import play.api.{Environment, Mode}
import com.google.inject.AbstractModule

class DatabaseInitializer @Inject()(environment: Environment) {
  environment.mode match {
    case Mode.Dev =>
    // Start dev database
    case Mode.Test =>
    // Start test database
    case Mode.Prod =>
    // Start prod database
  }
}

class DatabaseInitializerModule extends AbstractModule {
  override def configure() = {
    bind(classOf[DatabaseInitializer]).asEagerSingleton()
  }
}

编辑: 替换
GlobalSettings.onStart
的一种更为惯用且推荐的方法是:

GlobalSettings.beforeStart
GlobalSettings.onStart
:启动时需要发生的任何事情现在都应该发生在依赖项注入类的构造函数中。当依赖项注入框架加载类时,该类将执行其初始化。如果您需要快速初始化(因为您需要在应用程序实际启动之前执行一些代码)

因此,我们可以将您的代码重写为如下内容:

import com.google.inject.AbstractModule
import play.api.{Configuration, Environment, Mode}

class DatabaseInitializerModule(
  environment: Environment,
  configuration: Configuration
) extends AbstractModule {

  def configure() = {
    environment.mode match {
      case Mode.Dev =>
        // Start dev database
      case Mode.Test =>
        // Start test database
      case Mode.Prod =>
        // Start prod database
    }
  }
}
import javax.inject.Inject

import play.api.{Environment, Mode}
import com.google.inject.AbstractModule

class DatabaseInitializer @Inject()(environment: Environment) {
  environment.mode match {
    case Mode.Dev =>
    // Start dev database
    case Mode.Test =>
    // Start test database
    case Mode.Prod =>
    // Start prod database
  }
}

class DatabaseInitializerModule extends AbstractModule {
  override def configure() = {
    bind(classOf[DatabaseInitializer]).asEagerSingleton()
  }
}

注意我是如何删除了trait的,因为它没有在这里添加任何值。

编译错误是怎么说的?我也不清楚为什么在trait和扩展trait的类中都使用类型参数
Environment
。它应该在没有类型参数的情况下工作。“实现限制:当前不支持批注上的多个参数列表。”我正在尝试访问/传递环境对象以查找模式,以便可以初始化所需的db。这很有趣。如何编译代码?昨天或前一天,我在Stackoverflow上看到一个类似编译错误的问题,但由于某种原因,它很快就被删除了。我认为Intellij IDEA存在问题。无论如何,我认为它没有资格将依赖项传递给
AbstractModule
构造函数。您需要将它们注入到
MyInitClass
的构造函数或字段中。此外,据我所知,您不能仅使用带类型参数的
bind
绑定泛型类型。您需要使用
TypeLiteral
参数重命名在IntelliJ中仍然显示为错误。但是下面的过程更直接,而且很有效。然而,我想知道在Play2.5.x中是否有一个规定的设计模式,用于基于使用DI的模式进行初始化。如果不需要这样的解决方案,我会将此标记为答案。谢谢我重命名了类型参数,只是为了避免混淆其名称和
play.api.Environment
。我觉得你把这里的概念搞混了。无论如何,这里介绍了替换/删除GlobalSettings的最推荐方法:。我将编辑我的答案,以使您的代码适应我认为更惯用的内容。是的,trait用法是多余的。在我的例子中,我添加了一行,它直接在configure()内部的db connector对象中设置模式。这样,MyInit类保持完全相同,初始化db的调用将在实际的db init对象上进行,模式已经设置。然而,我把你的答案标记为接受答案。谢谢