如何在Play 2.6控制器中使"CustomExecutionContext"可用于依赖项注入? [英] How do make a `CustomExecutionContext` available for dependency injection in a Play 2.6 controller?

查看:126
本文介绍了如何在Play 2.6控制器中使"CustomExecutionContext"可用于依赖项注入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在跟播放2.6'用于创建非阻塞操作的Scala文档和示例代码,并且遇到了一些运行时问题.我已经使用 Scala模板( sbt new playframework/play-scala-seed.g8).

I'm following along with Play 2.6's Scala documentation and sample code for creating non-blocking actions, and am running into some runtime issues. I have created a new Play application using the Scala template (sbt new playframework/play-scala-seed.g8).

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

The code that the Play documentation suggests should work in a new controller is (this code is taken verbatim from the Play documentation page, with some extra imports from me):

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

然后,根据文档,以使用其他线程池,我已经在应用程序的application.conf文件中定义了my.executor线程池:

Then, according to the documentation for using other thread pools, I've defined the my.executor thread pool in the application.conf file of my application:

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

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

I should note that I do not want to use the default execution context as I want to prepare for running futures in a separate context that may be used for a limited resource like a database connection pool.

所有这些都可以通过sbt compile正常编译.但是,当我用sbt run运行它并在Web浏览器中访问我的应用程序时,出现此错误:

All of this compiles just fine with sbt compile. However, when I run this with sbt run and access my app in a web browser, I get this error:

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

CreationException: Unable to create injector, see the following errors:

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)

1) No implementation for controllers.MyExecutionContext was bound. while locating controllers.MyExecutionContext for the 1st parameter of controllers.NewController.(NewController.scala:17) while locating controllers.NewController for the 2nd parameter of router.Routes.(Routes.scala:29) at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121): Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

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

I've used Play 2.3 in the past, and know that dependency injection works when you define an instance of an object (via @Singleton or in a module); however, Play 2.6's documentation on DI indicates that "Guice is able to automatically instantiate any class with an @Inject on its constructor without having to explicitly bind it. This feature is called just in time bindings is described in more detail in the Guice documentation."

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

My question is: what specific lines of code or configuration do I need to add to Play's own sample to make this work, and why?

推荐答案

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

The simplest way to bind an implementation to an interface is to use the Guice @ImplementedBy annotation.

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

So, by adding that to the my MyExecutionContext trait, like so:

import com.google.inject.ImplementedBy

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

实例化MyExecutionContextImpl的一个实例并将其正确注入到控制器中.

an instance of the MyExecutionContextImpl is instantiated and properly injected into the controller.

很遗憾,该@ImplementedBy注释未在非阻止操作文档!

Too bad that this @ImplementedBy annotation isn't listed in the sample code for the non-blocking action documentation!

这篇关于如何在Play 2.6控制器中使"CustomExecutionContext"可用于依赖项注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆