【问题标题】:akka actor current receive function nameakka 演员当前接收函数名称
【发布时间】:2018-04-27 18:11:55
【问题描述】:

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

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 自己

记录当前接收函数

将行为更改为行为栏

ping 自己

记录当前接收函数

在这两种情况下,它都会记录“$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”

是否存在任何获取当前行为(接收)函数名称的方法? 或者我需要随时像 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")
}

那么,我的actor代码就变成了

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

现在日志看起来像

...你好:behaviourFoo 得到了 Ping

...你好:behaviourBar 得到了 Ping

【问题讨论】:

    标签: akka akka-actor


    【解决方案1】:

    也许这就是为什么那些被称为匿名函数的原因。 behaviorFoo, behaviorBar, ... 名称对这些匿名函数没有影响。为了说明这一点,考虑一下:

    // 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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 2014-11-15
      • 2013-11-29
      • 2015-03-27
      • 2014-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多