注入的Akka RouterActor

时间:2017-10-28 15:36:19

标签: scala akka actor playframework-2.6

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

配置

  • Java 1.8.0_144
  • Scala 2.12.3
  • 播放 2.6.5

我有以下代码:
ExampleController

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()
  }

}

ChildActor

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 的路线时,我会在控制台上看到所有演员的 println ,但 InjectedRouterActor 除外。

无法理解为什么?任何帮助表示赞赏。

由于

1 个答案:

答案 0 :(得分:0)

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

在您的示例中RoundRobinPool(5).props(Props[ChildActor])创建Props,它将创建循环池路由器,路由器为ChildActor类型的actor。你真的不需要InjectedRouterActor。如果要根据配置创建路由器,您可能仍希望拥有它(请参阅Akka docs中的示例)。

如果你看一下使用Guice helper时创建actor的ActorRefProvider的来源

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类型参数传递)但是,因为您提供了{{ 1}}作为忽略函数参数的函数(props),它将忽略_ => RoundRobinPool(5).props(Props[ChildActor])变量。另外creation作为名称参数传递给injector.instanceOf[T],因此不会立即调用它,因此不会创建Props#apply

您可以手动创建<{1}},而不是为InjectedRouterActor中的路由器角色创建绑定:

configure