'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 这样的东西,让它们隐式更好。
我想通过 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 这样的东西,让它们隐式更好。