我有一个主管和一个工人演员。工作线程调用服务。所有这些都由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
method(:
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")
现在的挑战是将此实例注入到管理引擎中。
感谢在这些方面的任何帮助:
- 当注入器仍在构建中时,如何在configure(((Module.scala(中访问Guice管理的WorkerActor.Factory?
- 我尝试使用带有WorkerActor.Factory作为参数的@Provides方法。但是 bindActor(( 调用只允许在 configure(( 中调用。不是@Provides方法。
- 我如何让播放注入
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。
只需为执行组件创建一个提供程序,注入ActorSystem
和Configuration
,即可创建执行组件并生成服务实例。
由于您需要拥有该Actor的两个实例,因此需要为它们使用不同的名称,并使用不同的名称在Guice中绑定它们。