'含糊不清的隐含价值观'将两个actor注入Play控制器时

时间:2017-07-17 20:11:18

标签: scala dependency-injection playframework akka guice

我想通过DI将两个演员注入Play控制器。注入一个演员的工作非常好,我可以毫无问题地向这个演员发送信息。但是,当注入第二个actor并发送消息时,我收到以下编译错误:

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

}

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

我尝试将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来与actor进行交互。但取决于你在控制器内做了什么 - 如果你需要像物化器或actorSystem这样的东西让它们隐含更好。