作为当前 actor 接收函数名
akka actor current receive function name
我有一个具有 2 个行为的简单演员
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 自己
记录当前接收函数
将行为更改为 behaviorBar
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")
}
然后,我的演员代码变成
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
也许这就是那些被称为匿名函数的原因。 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
这当然不值得麻烦,但它应该可以帮助您了解正在发生的事情。
我有一个具有 2 个行为的简单演员
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 自己
记录当前接收函数
将行为更改为 behaviorBar
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")
}
然后,我的演员代码变成
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
也许这就是那些被称为匿名函数的原因。 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
这当然不值得麻烦,但它应该可以帮助您了解正在发生的事情。