如何在Play 2.6控制器中使“ CustomExecutionContext”可用于依赖项注入?

时间:2018-11-05 21:38:52

标签: scala dependency-injection playframework

我与Play 2.6's Scala documentation and sample code for creating non-blocking actions一起关注,并且遇到了一些运行时问题。我已经使用Scala templatesbt new playframework/play-scala-seed.g8)创建了一个新的Play应用程序。

Play文档建议使用的代码应在新控制器上工作(此代码是从Play文档页面逐字记录的,其中还包括一些额外的导入信息):

// some imports added by me to get the code to compile
import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.concurrent.Future

import akka.actor.ActorSystem
import play.api.libs.concurrent.CustomExecutionContext
import play.api.mvc._
import play.api.mvc.ControllerComponents
// end imports added by me

import play.api.libs.concurrent.CustomExecutionContext

trait MyExecutionContext extends ExecutionContext

class MyExecutionContextImpl @Inject()(system: ActorSystem)
  extends CustomExecutionContext(system, "my.executor") with MyExecutionContext

class HomeController @Inject()(myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
  def index = Action.async {
    Future {
      // Call some blocking API
      Ok("result of blocking call")
    }(myExecutionContext)
  }
}

然后,根据documentation for using other thread pools,我在应用程序的my.executor文件中定义了application.conf线程池:

my.executor {
  fork-join-executor {
    parallelism-factor = 20.0
    parallelism-max = 200
  }
}

我应该注意,我不想使用默认执行上下文,因为我想为在单独的上下文中运行期货做准备,该上下文可能用于有限的资源,例如数据库连接池。

所有这些都可以使用sbt compile进行编译。但是,当我使用sbt run运行此程序并在网络浏览器中访问我的应用程序时,出现此错误:

  

CreationException:无法创建注射器,请参见以下错误:

     

1)没有为controllers.MyExecutionContext绑定的实现。     在定位controller.MyExecutionContext时       用于controllers.NewController的第一个参数。(NewController.scala:17)     在定位controller.NewController时       用于router.Routes的第二个参数。(Routes.scala:29)     在play.api.inject.RoutesProvider $ .bindingsFromConfiguration(BuiltinModule.scala:121)处:   绑定(路由器类。路由到自身)(通过模块:com.google.inject.util.Modules $ OverrideModule-> play.api.inject.guice.GuiceableModuleConversions $$ anon $ 1)

我过去使用过Play 2.3,并且知道当您定义对象的实例(通过@Singleton或在模块中)时,依赖项注入有效。但是,Play 2.6's documentation on DI表示“ Guice可以在其构造函数上使用@Inject自动实例化任何类,而不必显式绑定它。此功能在Guice文档中有更详细的描述,这称为及时绑定。 “

我的问题是:要使这项工作有效,我需要在Play自己的示例中添加哪些特定的代码行或配置?为什么?

1 个答案:

答案 0 :(得分:1)

在Scala依赖注入文档页面的Binding Annotations部分中进一步阅读时,我找到了一种可能的解决方案。特别指出:

  

将实现绑定到接口的最简单方法是使用Guice @ImplementedBy批注。

因此,通过将其添加到我的MyExecutionContext trait中,如下所示:

import com.google.inject.ImplementedBy

@ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext

实例化MyExecutionContextImpl的实例并将其正确注入控制器。

可惜的是,non-blocking action文档的示例代码中没有列出此@ImplementedBy注释!