如何在 Play 2.6 控制器中使“CustomExecutionContext”可用于依赖注入?
Posted
技术标签:
【中文标题】如何在 Play 2.6 控制器中使“CustomExecutionContext”可用于依赖注入?【英文标题】:How do make a `CustomExecutionContext` available for dependency injection in a Play 2.6 controller? 【发布时间】:2018-11-05 21:38:52 【问题描述】:我正在关注Play 2.6's Scala documentation and sample code for creating non-blocking actions,但遇到了一些运行时问题。我使用Scala template (sbt 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,我在我的应用程序的application.conf
文件中定义了my.executor
线程池:
my.executor
fork-join-executor
parallelism-factor = 20.0
parallelism-max = 200
我应该注意,我确实不想要使用默认的执行上下文,因为我想准备在单独的上下文中运行未来,该上下文可能用于数据库连接池等有限资源。
所有这些都可以使用sbt compile
编译得很好。但是,当我使用 sbt run
运行此程序并在网络浏览器中访问我的应用程序时,我收到此错误:
CreationException: 无法创建注入器,看到如下错误:
1) 没有绑定 controllers.MyExecutionContext 的实现。 在定位 controllers.MyExecutionContext 对于 controllers.NewController.(NewController.scala:17) 的第一个参数 在定位控制器时。NewController 对于 router.Routes.(Routes.scala:29) 的第二个参数 在 play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121): 绑定(class router.Routes to self)(通过模块: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 自己的示例添加哪些特定的代码行或配置才能使其正常工作,为什么?
【问题讨论】:
在你的项目中应该有一个Modules
文件可以让你绑定特定的实现。
【参考方案1】:
在进一步阅读 Scala 依赖注入文档页面的 Binding Annotations 部分时,我发现了一种可能的解决方案。它特别指出:
将实现绑定到接口的最简单方法是使用 Guice @ImplementedBy 注解。
所以,通过将其添加到我的MyExecutionContext
trait
,就像这样:
import com.google.inject.ImplementedBy
@ImplementedBy(classOf[MyExecutionContextImpl])
trait MyExecutionContext extends ExecutionContext
MyExecutionContextImpl
的一个实例被实例化并正确注入到控制器中。
太糟糕了,@ImplementedBy
注释没有在non-blocking action 文档的示例代码中列出!
【讨论】:
以上是关于如何在 Play 2.6 控制器中使“CustomExecutionContext”可用于依赖注入?的主要内容,如果未能解决你的问题,请参考以下文章
为 play framework 2.6 配置的默认控制器包在哪里?
在 Play 框架 Java 2.6 中添加 Paypal 按钮
在 Play 2.6 上使用 stb-native-packager 和 Debian 和 SystemV
将 Play 框架中的 WebSockets 从 2.4 版转换为 2.6 版