最近我从scala actor转换为akka actor,但注意到akka actor使用ActorRef
而不是实例对象:
val actorRef: ActorRef = Actor.actorOf(new MyActor)
所以我试过了:
val myActor = new MyActor
val actorRef: ActorRef = Actor.actorOf(x)
...同时拥有:1)ActorRef
发送消息,2)MyActor
来调用方法。
但我得到了:
akka.actor.ActorInitializationException: ActorRef for instance of actor [MyActor] is not in scope.
所以我的问题是:如何获得一个我可以调用ActorRef
的实例(某种类型) - 就像!
这样的方法以及来自MyActor
实例的方法?
答案 0 :(得分:14)
你正在做的是一个可怕的想法。所以现在就停下来,离开键盘,然后转到the Akka Documentation并阅读Actors。
考虑一下:
class YourActor extends Actor {
var mutableStuff = ...
def receive = {
case _ =>
// mess with mutableStuff
}
def publicMethod = // mess with mutableStuff
}
现在,设置系统并开始发送消息并从其他线程调用该方法。吊杆!
你正在做精确 Akka和Actor模型可以帮助你预防。你实际上是向后弯腰以打破他们已经修复过的东西:)他们不会让你这么做。
现在,您可以直接访问方法进行单元测试,但需要一个TestActorRef。在阅读文档时,请阅读有关测试的部分。
答案 1 :(得分:1)
我能做到的最好的是以下,非常脏:
还有更好的方法吗?
import akka.actor._
trait ActorCom {
var actorRefForInitialization: ActorRef = _
lazy val actorRef: ActorRef = actorRefForInitialization
def ?(message: Any)(implicit channel: UntypedChannel = NullChannel, timeout: Actor.Timeout = Actor.defaultTimeout) = actorRef ? message
def !(msg: Any)(implicit sender: UntypedChannel) = actorRef ! msg
def start = actorRef.start
}
object AkkaActorFactory {
def apply[A <: Actor](newInstance: => A with ActorCom): A with ActorCom = {
var instance: Option[A with ActorCom] = None
val actorRef = Actor.actorOf({
instance = Some(newInstance)
instance.get
})
instance.get.actorRefForInitialization = actorRef
instance.get.actorRef // touch lazy val in ActorCom, to make it equal to actorRef and then its fixed (immutable)
instance.get
}
}
class MyActor extends Actor {
def receive = {
case "test1" => println("good")
case "test2" => println("fine")
case _ => println("bad")
}
def sendTestMsg2Myself = self ! "test2"
}
val myActor = AkkaActorFactory(newInstance = new MyActor with ActorCom)
myActor.start
myActor ! "test1"
myActor.sendTestMsg2Myself // example for calling methods on MyActor-instance
myActor ! PoisonPill