1

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

配置

  • Java ( 1.8.0_144 )
  • 斯卡拉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")
  }

}

注入演员

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打路线时,我看到控制台上所有可见的演员的println s,除了InjectedRouterActor

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

谢谢

4

1 回答 1

0

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

在您的示例中RoundRobinPool(5).props(Props[ChildActor])创建Props将创建循环池路由器,其中 routees 是 type 的参与者ChildActor。你真的不需要InjectedRouterActor。如果您想基于配置创建路由器,您可能仍然希望拥有它(请参阅Akka 文档中的示例)。

如果您在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传递)的默认值,但是,由于您作为函数提供了忽略函数参数的函数(),它只会忽略变量。也作为按名称参数传递,因此不会立即调用它,因此不会创建您的。Tprops_ => RoundRobinPool(5).props(Props[ChildActor])creationinjector.instanceOf[T]Props#applyInjectedRouterActor

configure您可以手动创建它,而不是为路由器参与者创建绑定:

@Provides
@Named("injected-router")
@Singleton
def routerProvider(system: ActorSystem): ActorRef = {
  system.actorOf(RoundRobinPool(5).props(Props[ChildActor]), name = "injected-router")
}
于 2017-10-28T17:47:14.157 回答