用Guice向工厂提供的儿童演员注入服务

时间:2016-04-19 10:27:35

标签: scala akka guice

在我的应用程序中,我有一位主管,可以创建一些工作人员。这些工作程序中的每一个都需要两个QueueClients实例(具有不同的配置和工作程序之间的不同实例)。我是guice的新手,我遇到了在子actor中注入这些依赖项的问题。

这是我的工人阶级:

object LegacyConsumer {

  trait Factory {
    def apply(): Actor
  }

}

class LegacyConsumer @Inject()(
  eventsClient: QueueClient,
  deadLetterClient: QueueClient
) extends Actor with ActorLogging {

  override def preStart(): Unit = {
    log.error("prestart")
    log.error(eventsClient.toString)
  }

  def receive: PartialFunction[Any, Unit] = {
    case _ =>
      log.error("received message consumer")
  }
}

如您所见,我需要两个QueueClient进行构建:

trait QueueClient {
...

  def numMessages: Int
}

class SqsClient @Inject()(name: String, key: String, secret: String, zone: String) extends Logging with QueueClient {
...
}

这就是我尝试创建工作人员的方式

class LegacyConsumerSupervisor @Inject()(
  consumerFactory: LegacyConsumer.Factory,
  @Named("numWorkers") workers: Int
)
  extends Actor with ActorLogging with InjectedActorSupport {

  override def preStart(): Unit = {
    (1 to workers).foreach { workerNumber =>
      val key = s"WORKER-$workerNumber"
      injectedChild(consumerFactory(), key, _.withDispatcher("akka.legacy-consumer-dispatcher"))
    }
  }

最后这就是我的绑定看起来像

class ChatModule extends AbstractModule with ScalaModule with AkkaGuiceSupport{
  override def configure() {
    bind[Actor].annotatedWith(Names.named(LegacyConsumerSupervisor.name)).to[LegacyConsumerSupervisor]

    bind(classOf[Int])
      .annotatedWith(Names named "numWorkers")
      .toInstance(ConfigurationHelper.getInt("chat.legacy.num-workers"))

    bindActorFactory[LegacyConsumer, LegacyConsumer.Factory]

    bind(classOf[QueueClient])
//      .annotatedWith(Names named "legacyEventsClient")
        .toInstance(
          new SqsClient(
            ConfigurationHelper.getString("chat.legacy.events.name"),
            ConfigurationHelper.getString("chat.legacy.events.key"),
            ConfigurationHelper.getString("chat.legacy.events.secret"),
            ConfigurationHelper.getString("chat.legacy.events.region")
          )
        )

    bind(classOf[QueueClient])
//      .annotatedWith(Names named "legacyDeadLetterClient")
        .toInstance(
          new SqsClient(
            ConfigurationHelper.getString("chat.legacy.dead-letter.name"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.key"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.secret"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.region")
          )
        )
  }
}

如何将不同的队列客户端实例注入每个工作者?所有legacyEventsClients和legacyDeadLetterClients都具有相同的配置(基于typesafe配置)。该解决方案是否与辅助注射有关?

我现在得到的错误:

绑定到... QueueClient已配置为... configure(ChatModule.scala:29)。   at ... configure(ChatModule.scala:40)

所以我认为问题是关于尝试将相同的绑定两次注入到不同的实例中...我尝试使用命名参数但是然后将相同的客户端实例注入每个LegacyConsumer

此致

1 个答案:

答案 0 :(得分:0)

我终于做到了这一点并且有效:

绑定:

    bind(classOf[QueueClient])
      .annotatedWith(Names named "legacyEventsClient")
      .toProvider(new Provider[SqsClient] {
        override def get = {
          new SqsClient(
            ConfigurationHelper.getString("chat.legacy.events.name"),
            ConfigurationHelper.getString("chat.legacy.events.key"),
            ConfigurationHelper.getString("chat.legacy.events.secret"),
            ConfigurationHelper.getString("chat.legacy.events.region")
          )
        }
      })

    bind(classOf[QueueClient])
      .annotatedWith(Names named "legacyDeadLetterClient")
      .toProvider(new Provider[SqsClient] {
        override def get = {
          new SqsClient(
            ConfigurationHelper.getString("chat.legacy.dead-letter.name"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.key"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.secret"),
            ConfigurationHelper.getString("chat.legacy.dead-letter.region")
          )
        }
      })

在我的工人阶级:

class LegacyConsumer @Inject()(
  @Named("legacyEventsClient") eventsClient: QueueClient,
  @Named("legacyDeadLetterClient") deadLetterClient: QueueClient
) extends Actor with ActorLogging {

  override def preStart(): Unit = {
    log.error("prestart")
  }

  def receive: PartialFunction[Any, Unit] = {
    case _ =>
      log.error("received message consumer")
  }
}