【发布时间】:2020-03-31 22:55:53
【问题描述】:
我有一个主管和一个工人演员。工人调用服务。所有这些都由 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(configure 方法):
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")
现在的挑战是将这个实例注入到 Supervisor 中。
感谢您在这些方面的任何帮助:
- 当注入器仍在构建中时,如何在 configure() (Module.scala) 中访问 Guice 托管的 WorkerActor.Factory?
- 我尝试使用带有 WorkerActor.Factory 作为参数的@Provides 方法。但是 bindActor() 调用只允许在 configure() 中调用。不在@Provides 方法中。
- 如何让 Play 注入
workerFactory: WorkerActor.Factory但提供我自己的AService?。据我所知,bindActor(...)似乎不支持这一点。
编辑:
我的解决方案基于以下 Renato 的回答供将来使用:
我必须为所需的每个参与者实例(对象图)实现一个 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中绑定这个provider:
bind(classOf[ActorRef])
.annotatedWith(Names.named("propertyId1Actor"))
.toProvider(classOf[PropertyId1SupervisorActorProvider])
这确实需要一些工作才能让另一个实例运行。但这是我目前最好的解决方案。如果有关于改进这一点的建议,我会全力以赴。
【问题讨论】:
标签: scala playframework akka