未为注入的 Akka RouterActor 调用构造函数和 preStart/postStop 钩子

Constructor and preStart/postStop hooks NOT invoked for injected Akka RouterActor

我正在尝试 Play Framework (Scala) 中的一些示例。我正在将一个演员注入控制器。

配置

我有以下代码:
示例控制器

class ExampleController @Inject() (
  controllerComponents: ControllerComponents,
  @Named("injected-router") injectedRouterActor: ActorRef,
  @Named("injected") injectedActor: ActorRef)
  extends AbstractController(controllerComponents) {

  def alive = Action {
    injectedActor ! "Hi from Example"
    injectedRouterActor ! "Hi From Example to Router"
    Ok("Alive")
  }

}

InjectedActor

class InjectedActor extends Actor {

  val name = s"IA-${self.path}-${System.nanoTime}"

  println(s"constructor: $name")

  def receive = {
    case m => println(s"$name received: $m")
  }

  override def preStart() = {
    println(s"preStart: $name")
    super.preStart()
  }

}

InjectedRouterActor

class InjectedRouterActor extends Actor {

  val name = s"IRA-${self.path}-${System.nanoTime}"

  println(s"constructor: $name")

  def receive = {
    case m => println(s"$name received: $m")
  }

  override def preStart() = {
    println(s"preStart: $name")
    super.preStart()
  }

}

儿童演员

class ChildActor extends Actor {

  val name = s"CH-${self.path}-${System.nanoTime}"

  println(s"constructor: $name")

  def receive = {
    case m => println(s"$name received: $m")
  }

}

模块

class BindingModule extends AbstractModule with AkkaGuiceSupport {

  def configure = {
    bindActor[InjectedActor]("injected")
    bindActor[InjectedRouterActor]("injected-router", _ => RoundRobinPool(5).props(Props[ChildActor]))
  }

}

当我 运行 执行此操作并点击 alive 的路由时,我在控制台上看到所有参与者的 printlns , 除了 InjectedRouterActor.

无法理解为什么?感谢任何帮助。

谢谢

在 Akka 中,路由器是您未显式实现的特殊实现参与者。

在您的示例中,RoundRobinPool(5).props(Props[ChildActor]) 创建了 Props,这将创建循环池路由器,路由是 ChildActor 类型的参与者。你真的不需要 InjectedRouterActor。如果你想根据配置创建路由器,你可能仍然想要它(参见 Akka docs 中的示例)。

如果您查看 ActorRefProvider 的源代码,当您使用 Guice 助手时创建角色

class ActorRefProvider[T <: Actor: ClassTag](name: String, props: Props => Props) extends Provider[ActorRef] {

  @Inject private var actorSystem: ActorSystem = _
  @Inject private var injector: Injector = _
  lazy val get = {
    val creation = Props(injector.instanceOf[T])
    actorSystem.actorOf(props(creation), name)
  }
}

你可以看到它创建了默认值 Props 从注入器获取 InjectedRouterActor 的实例(类型信息作为 T 类型参数传递)但是,因为你提供props 作为忽略函数参数 (_ => RoundRobinPool(5).props(Props[ChildActor])) 的函数,它只会忽略 creation 变量。此外 injector.instanceOf[T] 作为别名参数传递给 Props#apply,因此不会立即调用它,因此不会创建您的 InjectedRouterActor

您可以手动创建它,而不是在 configure 中为路由器角色创建绑定:

@Provides
@Named("injected-router")
@Singleton
def routerProvider(system: ActorSystem): ActorRef = {
  system.actorOf(RoundRobinPool(5).props(Props[ChildActor]), name = "injected-router")
}