如何在Play 2.6控制器中使"CustomExecutionContext"可用于依赖项注入? [英] How do make a `CustomExecutionContext` available for dependency injection in a Play 2.6 controller?
问题描述
我正在跟播放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. 因此,通过将其添加到我的 So, by adding that to the my 实例化 an instance of the 很遗憾,该 Too bad that this 这篇关于如何在Play 2.6控制器中使"CustomExecutionContext"可用于依赖项注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
MyExecutionContext
trait
中,如下所示:MyExecutionContext
trait
, like so:import com.google.inject.ImplementedBy
@ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext
MyExecutionContextImpl
的一个实例并将其正确注入到控制器中.MyExecutionContextImpl
is instantiated and properly injected into the controller.@ImplementedBy
注释未在非阻止操作文档!@ImplementedBy
annotation isn't listed in the sample code for the non-blocking action documentation!