akka actor当前接收函数名称

时间:2017-11-14 17:26:29

标签: akka akka-actor

我有一个有两个行为的简单演员

package com.hello

import akka.actor.{Actor, ActorLogging}

case object Ping

class Hello extends Actor with ActorLogging {

  import context._

  def receive: Receive = behaviorFoo

  self ! Ping

  def behaviorFoo: Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
      become(behaviorBar)
      self ! Ping
  }

  def behaviorBar: Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
  }
}

这件事做那些:

ping self

记录当前接收功能

将行为更改为behaviorBar

ping self

记录当前接收功能

在两种情况下都会记录“$ anonfun $ behaviorFoo $ 1”

为什么在第二个日志中不是“$ anonfun $ behaviorBar $ 1”?

如果我将代码更改为

  self ! Ping

  def receive: Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
      become(behaviorFoo)
      self ! Ping
  }

  def behaviorFoo: Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
      become(behaviorBar)
      self ! Ping
  }

  def behaviorBar: Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
  }

它记录3次“$ anonfun $ receive $ 1”

是否存在获取当前行为(Receive)函数名称的任何方式? 或者我需要随时像log.info(“behaviorFoo”)那样硬写?

更新

对于记录问题,我添加了

trait MyLogging extends ActorLogging {
  this: Actor ⇒

  private[this] val actorClassName = this.getClass.getSimpleName

  private[this] var receiveName: String = {
    val receiveClassName = s"${this.receive.getClass.getSimpleName}"
    val left = receiveClassName.substring(0, receiveClassName.lastIndexOf("$"))
    left.substring(left.lastIndexOf("$") + 1)
  }

  def become(behavior: Actor.Receive): Unit = {
    val behaviorClassName = behavior.getClass.getSimpleName
    val left = behaviorClassName.substring(0, behaviorClassName.lastIndexOf("$"))

    receiveName = left.substring(left.lastIndexOf("$") + 1)

    context.become(behavior)
  }

  def info(message: Any): Unit = log.info(s"$actorClassName : $receiveName got $message")
}

然后,我的演员代码变成

class Hello extends Actor with MyLogging {

  def receive: Receive = behaviorFoo

  self ! Ping

  def behaviorFoo: Receive = {
    case any =>
      info(any)
      become(behaviorBar)
      self ! Ping
  }

  def behaviorBar: Receive = {
    case any => info(any)
  }
}

现在日志看起来像

...您好:behaviorFoo得到Ping

...你好:behaviorBar得到Ping

1 个答案:

答案 0 :(得分:1)

也许这就是为什么那些被称为匿名函数。 behaviorFoobehaviorBar,...名称对这些匿名函数没有影响。为了说明这一点,请考虑以下事项:

// this is a val!
val behaviorFoo: Receive = {
  case _ =>
    log.info(this.receive.getClass.getSimpleName)
    become(behaviorBar)
    self ! Ping
}
// this returns the same anonymous function
def behaviorFoo2 = behaviorFoo

通过上述内容,您应该看到存储匿名函数的名称与匿名函数本身无关...

现在,如果您意识到这些匿名函数是什么(它们是部分函数,​​别名为Actor.Receive),您可以执行以下操作:

// not an anonymous function anymore
class BehaviourFoo extends Actor.Receive {
  val anonymousFun: Actor.Receive = {
    case _ =>
      log.info(this.receive.getClass.getSimpleName)
      become(behaviorBar)
      self ! Ping
  }
  override def isDefinedAt(x: Any) = anonymousFun.isDefinedAt(x)

  override def apply(x: Any) = anonymousFun(x)
}
// again, the name behaviorFoo doesn't matter
def behaviorFoo: Receive = new BehaviourFoo

这当然不值得麻烦,但它应该可以帮助你了解正在发生的事情。