Dependency injection Play Framework,Akka,Guice:如何使用控制器内的Guice创建一个参与者(具有依赖项)的多个实例?
play framework doc()中有一个示例,解释了如何将actor(具有要注入的依赖项)注入控制器:Dependency injection Play Framework,Akka,Guice:如何使用控制器内的Guice创建一个参与者(具有依赖项)的多个实例?,dependency-injection,playframework-2.0,akka,guice,Dependency Injection,Playframework 2.0,Akka,Guice,play framework doc()中有一个示例,解释了如何将actor(具有要注入的依赖项)注入控制器: @Singleton class Application @Inject() (@Named("configured-actor") configuredActor: ActorRef) (implicit ec: ExecutionContext) extends Controller { implicit val timeout: Timeout = 5.secon
@Singleton
class Application @Inject()
(@Named("configured-actor") configuredActor: ActorRef)
(implicit ec: ExecutionContext) extends Controller {
implicit val timeout: Timeout = 5.seconds
def getConfig = Action.async {
(configuredActor ? GetConfig).mapTo[String].map { message =>
Ok(message)
}
}
}
但据我所知,它创建了一个actor实例(例如,singleton)
我需要在控制器内创建多个configuredActor
实例
还有一个示例演示如何从父参与者创建子参与者(具有要注入的依赖项)实例
object ParentActor {
case class GetChild(key: String)
}
class ParentActor @Inject() (
childFactory: ConfiguredChildActor.Factory
) extends Actor with InjectedActorSupport {
import ParentActor._
def receive = {
case GetChild(key: String) =>
val child: ActorRef = injectedChild(childFactory(key), key)
sender() ! child
}
}
我曾尝试在控制器内部应用此技术,但injectedChild(childFactory(key),key)
需要(隐式)参与者上下文
def injectedChild(create: => Actor, name: String, props: Props => Props = identity)(implicit context: ActorContext): ActorRef = ...
但是我需要从ActorySem(例如/user)创建这个演员
(我想了解/user
actor的上下文,但怎么知道?对吗?)
用Guice在父actor外部(例如,在控制器内部)创建多个actor实例的正确方法是什么?我认为没有从actor外部获取ActorContext的方法,但是如果您想从/user actor创建子actor,可以直接执行
system.actorOf
问题就像你说的,InjectedActorSupport
需要一个ActorContext。
但是如果你看这个特征,它不会做任何花哨的事情,只是
def injectedChild(create: => Actor, name: String, props: Props => Props = identity)(implicit context: ActorContext): ActorRef = {
context.actorOf(props(Props(create)), name)
}
因此,解决方案是扩展trait并添加一个接收ActorSystem而不是ActorContext的方法
def injectedChild2(create: => Actor, name: String, props: Props => Props = identity)(implicit system: ActorSystem): ActorRef = {
system.actorOf(props(Props(create)), name)
}
事实上,您甚至可以直接将该方法添加到控制器中,但如果要在多个控制器中执行此操作,则不方便
更新:
虽然这在技术上是正确的,但我(正确地)认为缺少接收ActorSystem的方法是有意的
所以,我和詹姆斯·罗珀回答:
原因是直接从actor系统外部创建多个actor通常不是一种好的做法,因为您不能监督他们-也就是说,您不能说当他们崩溃时会发生什么(应该停止、重新启动、升级等?)。在我希望从控制器创建一个参与者的所有场景中,对我来说,最好的设计是不这样做,而是向另一个经理参与者发送消息来创建子参与者。当您这样做时,在将来为您提供了更大的灵活性,例如,假设将来您有一个要求,即当用户重新提交相同的操作时,它不应该启动新的参与者,而应该连接到现有的参与者。如果您有一个管理者参与者,这很容易做到,您可以原子式地检查管理者参与者是否已经有该操作的子级,并在必要时创建一个新的子级。如果不是,那是不可能的。然后在将来,您将转向多节点设置,您可能会决定在集群中分片您的参与者-同样,如果您使用的是manager参与者,则非常容易,因为您需要做的只是将manager参与者替换为集群分片,或者在manager前面放置一个集群一致哈希路由器,但如果直接从控制器创建参与者,则不可能