scala - 播放框架 2.5.x : Inject Environment in a Module

标签 scala dependency-injection guice playframework-2.5

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

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
    }
  }
}

编辑:

替换 GlobalSettings.onStart 的更惯用和推荐的方法是 described at the docs :

GlobalSettings.beforeStart and GlobalSettings.onStart: Anything that needs to happen on start up should now be happening in the constructor of a dependency injected class. A class will perform its initialisation when the dependency injection framework loads it. If you need eager initialisation (because you need to execute some code before the application is actually started), define an eager binding.



因此,我们可以将您的代码重写为如下所示:
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因为它在这里没有增加任何值(value)。

关于scala - 播放框架 2.5.x : Inject Environment in a Module,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37648388/

相关文章:

scala - 在游戏中使用 ActionBuilder 创建自定义 Action 时使用 guice

java - 多核性能如何与 Scala 中的执行上下文和线程池相关

python - 动态语言中依赖注入(inject)的真实示例是什么?

scala - 使用 Gatling 进行可变斜升

java - @Inject 和 @Named 注释给出 NoSuchBeanDefinitionException

dependency-injection - casperjs:如何在单元测试期间在测试本身中包含其他 javascript 文件?

java - 为什么使用 Guice Provider 而不是普通注入(inject)

java - 如何使用 ServletScopes.scopeRequest() 和 ServletScopes.continueRequest()?

scala - Scala:参数化类型只是语法糖(如Odersky所建议)吗?

scala - 有没有办法使用对象的类型作为类型参数的参数?