将构造函数参数传递给 Play 托管的 Actor



我有一个主管和一个工人演员。工作线程调用服务。所有这些都由Play(/Guice(管理。

以下是代码的简化:

class SupervisorActor @Inject()(workerFactory: WorkerActor.Factory, serviceA: AService)
extends Actor
with InjectedActorSupport {
override def receive: Receive = {
case message => injectedChild(workerFactory(serviceA), "childActorName").forward(message)
}
}
class WorkerActor @Inject()(serviceA: AService) extends Actor {
override def receive: Receive = {
case _ => println(serviceA.getMessage())
}
}
object WorkerActor {
trait Factory {
def apply(serviceA: AService): Actor
}
}
@ImplementedBy(classOf[AServiceImpl])
trait AService {
def getMessage(): String
}
class AServiceImpl @Inject()(configuration: Configuration) extends AService {
override def getMessage(): String = configuration.get[String]("id1")
}

Module.scala(configuremethod(:

bindActor[SupervisorActor]("supervisor")
bindActorFactory[WorkerActor, WorkerActor.Factory]

一切都很完美。到目前为止,每个类都有一个实例。

现在,AServiceImpl.getMessage()需要查找动态字符串(不仅仅是每次都查找"id1"(。所以改成这样:

class AServiceImpl @Inject()(configuration: Configuration, propertyId: String) extends AService {
override def getMessage(): String = configuration.get[String](propertyId)
}

并从trait AService中删除了@ImplementedBy(classOf[AServiceImpl]).

这个想法是实例化主管,工人和服务的2个实例,并将它们连接到Module.scala中。所以我从Module.scala开始

val aServive: AService = new AServiceImpl(configuration, "id1")

现在的挑战是将此实例注入到管理引擎中。

感谢在这些方面的任何帮助:

  1. 当注入器仍在构建中时,如何在configure(((Module.scala(中访问Guice管理的WorkerActor.Factory?
  2. 我尝试使用带有WorkerActor.Factory作为参数的@Provides方法。但是 bindActor(( 调用只允许在 configure(( 中调用。不是@Provides方法。
  3. 我如何让播放注入workerFactory: WorkerActor.Factory但提供我自己的AService?据我所知,bindActor(...)似乎不支持这一点。

编辑:

我的解决方案基于雷纳托的以下答案以供将来使用:

我必须为所需的参与者(对象图(的每个实例实现一个 ActorRef 提供程序。这样:

class PropertyId1SupervisorActorProvider @Inject()(configuration: Configuration,
workerFactory: WorkerActor.Factory,
actorSystem: ActorSystem)
extends Provider[ActorRef] {
override def get(): ActorRef = {
val aService: AService = new AServiceImpl(configuration, "propertyId1")
actorSystem.actorOf(Props(classOf[SupervisorActor], workerFactory, aService))
}
}

然后在 Module.scala 中绑定此提供程序:

bind(classOf[ActorRef])
.annotatedWith(Names.named("propertyId1Actor"))
.toProvider(classOf[PropertyId1SupervisorActorProvider])

这确实需要一些工作才能让另一个实例运行。但这是我目前拥有的最佳解决方案。如果有关于改进这一点的建议,我全听。

我认为您可以通过使用一个无需过多依赖任何 Guice 布线即可完成所有操作的提供程序来简化它。提供程序应返回要注入到系统其他部分的 Actor。Actor 下的所有图形都可以而且应该隐藏,换句话说,不会暴露给 DI。

只需为执行组件创建一个提供程序,注入ActorSystemConfiguration,即可创建执行组件并生成服务实例。

由于您需要拥有该Actor的两个实例,因此需要为它们使用不同的名称,并使用不同的名称在Guice中绑定它们。

最新更新