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

2024-06-21

我正在跟随Play 2.6 的 Scala 文档和示例代码用于创建非阻塞操作 https://www.playframework.com/documentation/2.6.x/ScalaAsync#Creating-non-blocking-actions,并且遇到了一些运行时问题。我使用以下命令创建了一个新的 Play 应用程序Scala 模板 https://www.playframework.com/documentation/2.6.x/NewApplication#Scala-template (sbt new playframework/play-scala-seed.g8).

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

然后,根据使用其他线程池的文档 https://www.playframework.com/documentation/2.6.x/ThreadPools#Using-other-thread-pools,我定义了my.executor线程池中的application.conf我的申请文件:

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

我应该注意到我这样做not想要使用默认执行上下文,因为我想准备在单独的上下文中运行 future,该上下文可用于数据库连接池等有限资源。

所有这些都可以很好地编译sbt compile。但是,当我运行这个sbt run并在网络浏览器中访问我的应用程序,我收到此错误:

CreationException: 无法创建注入器,看到以下错误:

1)没有绑定controllers.MyExecutionContext的实现。 查找controllers.MyExecutionContext时 对于controllers.NewController.(NewController.scala:17)的第一个参数 在定位controllers.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 的 DI 文档 https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection#Declaring-runtime-DI-dependencies表示“Guice 能够在其构造函数上使用 @Inject 自动实例化任何类,而无需显式绑定它。此功能称为即时绑定,Guice 文档中有更详细的描述。”

我的问题是:我需要在 Play 自己的示例中添加哪些特定的代码或配置行才能使其正常工作,为什么?


我在进一步阅读时发现了一种可能的解决方案绑定注释 https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection#Binding-annotationsScala 依赖注入文档页面的部分。它特别指出:

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

因此,通过将其添加到我的MyExecutionContext trait,像这样:

import com.google.inject.ImplementedBy

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

的一个实例MyExecutionContextImpl被实例化并正确注入到控制器中。

可惜了这个@ImplementedBy示例代码中未列出注释非阻塞动作 https://www.playframework.com/documentation/2.6.x/ScalaAsync#Creating-non-blocking-actions文档!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使“CustomExecutionContext”可用于 Play 2.6 控制器中的依赖项注入? 的相关文章

随机推荐