Akka拦截接收具有可堆叠的行为

HiC*_*123 2 scala slf4j interceptor mdc akka

Akka和Scala新手在这里,请随时编辑这个问题,以便清楚地表达我在Scala和Akka领域的意图.

在我展示代码片段之前,这是我想要解决的问题:我本质上想要为我的团队开发一个通用模块,以便在他们使用Akka actor开发应用程序时使用.我想让它们混合一个特性,它将在运行时扩展它们的接收功能,主要用于记录目的.我遇到了编译错误,我很快就会解释.

但首先,举一个简单的主要内容:

object Test extends App {

   val system = ActorSystem("system")
   val myActor = system.actorOf(Props(new MyActor), "myActor")
   myActor ! "Hello world!"
}
Run Code Online (Sandbox Code Playgroud)

以下是团队成员可能在其应用程序中实现的actor的示例实现:

class MyActor extends Actor with ActorLogger {

   override def receive: Receive = {
       case msg => {
          log.info("testing ...")
       }
       case _ => throw new RuntimeException("Runtime Ex")
   }
}
Run Code Online (Sandbox Code Playgroud)

这是一个如何为他们提供混合的共同特征的例子:

trait ActorLogger extends Actor {

    val log: DiagnosticLoggingAdapter = Logging(this)

    abstract override def receive: Receive = {

         case msg: Any => {
            if (msg.isInstanceOf[String]) {
              println("enter")
              log.mdc(Map[String, Any]("someKey" -> 123))
              super.receive(msg)
              log.clearMDC()
               println("exit")
            }
          }

         case _ => throw new RuntimeException("Runtime Ex")
    }

}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我正在尝试将数据添加到MDC,如果消息恰好是String(一个基本的例子,实际上,我会检查我们自己的一些自定义类型).

我得到的错误是:

 Error:(29, 16) overriding method receive in trait ActorLogger of type =>   
 MyActor.this.Receive;
 method receive needs `abstract override' modifiers
 override def receive: Receive = {
           ^
Run Code Online (Sandbox Code Playgroud)

这有什么不对?并且堆叠特性是否有权通过消失来实现这样的目标?如果不是,那么最惯用的方式是什么?

更一般地说,除了"拦截器"模式之外还有其他模式吗?

感谢您的帮助!

Ser*_*nko 6

一个没有黑客akka包的解决方案:

import akka.actor.{Actor, ActorSystem, Props}

trait MyActorExtension extends Actor {

  def receiveExtension: Receive = PartialFunction.empty

}

abstract class MyActor extends MyActorExtension {

  protected def receiveMsg: Receive

  def receive: Receive = receiveExtension orElse receiveMsg

}

trait ActorLogger1 extends MyActor with MyActorExtension {

  abstract override def receiveExtension = {
    case msg =>
      println(s"********** Logging # 1: $msg")
      super.receiveExtension.applyOrElse(msg, receiveMsg)
  }

}

trait ActorLogger2 extends MyActor with MyActorExtension {

  abstract override def receiveExtension = {
    case msg =>
      println(s"########## Logging # 2: $msg")
      super.receiveExtension.applyOrElse(msg, receiveMsg)
  }
}

class SpecificActor extends MyActor with ActorLogger1 with ActorLogger2 {

  def receiveMsg = {
    case someMsg =>
      println(s"SpecificActor: $someMsg")
  }
}

object Test extends App {

  val system = ActorSystem("system")
  val mySpecificActor = system.actorOf(Props(new SpecificActor), "SpecificActor")
  mySpecificActor ! "Hello world!"
}
Run Code Online (Sandbox Code Playgroud) ####记录#2:Hello world!

******记录#1:你好世界!

SpecificActor:Hello world!