'ambiguous implicit values' 将两个 actor 注入 Play 控制器时

'ambiguous implicit values' when injecting two actors into Play controller

我想通过 DI 将两个演员注入到播放控制器中。注入一个演员绝对没问题,我可以毫无问题地向这个演员发送消息。但是,当注入第二个演员并发送消息时,出现以下编译错误:

play.sbt.PlayExceptions$CompilationException: Compilation error[ambiguous implicit values:
 both value fooSupervisor in class MyController of type akka.actor.ActorRef
 and value barSupervisor in class MyController of type akka.actor.ActorRef
 match expected type akka.actor.ActorRef]

我的控制器看起来像这样:

class MyController @Inject()(
                                           implicit system: ActorSystem,
                                           materializer: Materializer,
                                           @Named("FooSupervisor") fooSupervisor: ActorRef,
                                           @Named("BarSupervisor") barSupervisor: ActorRef
                                         ) extends Controller {


}

模块如下所示:

class Module extends AbstractModule with ScalaModule with AkkaGuiceSupport {

  def configure() {
    // ....
    bindActor[FooSupervisor]("FooSupervisor")
    bindActor[BarSupervisor]("BarSupervisor")
    ()
  }

}

我该如何解决这个问题?

您将这两个角色定义为隐式参数。像这样更改签名:

class MyController @Inject()(
  @Named("FooSupervisor") fooSupervisor: ActorRef,
  @Named("BarSupervisor") barSupervisor: ActorRef
  )(implicit system: ActorSystem, materializer: Materializer
  ) extends Controller {

我尝试将 actorRef 从供应商注入控制器。

import javax.inject._
import akka.actor.ActorRef
import play.api.mvc._

@Singleton
class HomeController @Inject()(@Named("actor1") val actor1: ActorRef, @Named("actor2") val actor2: ActorRef) extends Controller {
  def index = Action {
    actor1 ! "hello actor1"
    actor2 ! "hello actor2"
    Ok("Hello")
  }
}

模块应该绑定 actorRef。

import javax.inject.{Inject, Provider}
import com.google.inject.AbstractModule
import net.codingwell.scalaguice.ScalaModule
import actors.{Actor1, Actor2}
import akka.actor.{ActorRef, ActorSystem, Props}

class Module extends AbstractModule with ScalaModule{
  override def configure() = {
    bind[ActorRef].annotatedWithName("actor1").toProvider[Actor1Provider]
    bind[ActorRef].annotatedWithName("actor2").toProvider[Actor2Provider]
  }
}

class Actor1Provider @Inject() (system: ActorSystem) extends Provider[ActorRef]{
  override def get(): ActorRef = system.actorOf(Props[Actor1])
}

class Actor2Provider @Inject() (system: ActorSystem) extends Provider[ActorRef]{
  override def get(): ActorRef = system.actorOf(Props[Actor2])
}

如果您需要实体化器和actorSystem,请将它们作为隐式参数传递。由于我们已经注入了 actorRef 本身,我们可能不需要 actorSystem 来与演员交互。但是取决于你在控制器内部做了什么——如果你需要像 materializer 或 actorSystem 这样的东西,让它们隐式更好。