Dependency injection Play Framework,Akka,Guice:如何使用控制器内的Guice创建一个参与者(具有依赖项)的多个实例?

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

play framework doc()中有一个示例,解释了如何将actor(具有要注入的依赖项)注入控制器:

@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前面放置一个集群一致哈希路由器,但如果直接从控制器创建参与者,则不可能