私はプレイを使用していない似たような
を達成するためにhttps://github.com/rocketraman/activator-akka-scala-guiceに基づいていくつかのコードを使用していますので、私はGuiceのを初期化し、そこのGuiceを初期化するには俳優のシステム
import akka.actor._
import javax.inject.{Inject, Provider, Singleton}
import com.google.inject.AbstractModule
import net.codingwell.scalaguice.InjectorExtensions._
import com.google.inject.Guice
import com.google.inject.Injector
import scala.concurrent.Await
import scala.concurrent.duration.Duration
object Bootstrap extends App {
val injector = Guice.createInjector(
new AkkaModule(),
new ServiceModule()
)
implicit val system = injector.instance[ActorSystem]
val parentActor1 = system.actorOf(ParentActor.props(ChildActorA.name))
val parentActor2 = system.actorOf(ParentActor.props(ChildActorB.name))
parentActor1 ! "Message"
parentActor2 ! "Message"
system.terminate()
Await.result(system.whenTerminated, Duration.Inf)
}
をブートストラップする必要があります
つ拡張を初期化し、
import akka.actor.ActorSystem
import AkkaModule.ActorSystemProvider
import com.google.inject.{AbstractModule, Injector, Provider}
import com.typesafe.config.Config
import net.codingwell.scalaguice.ScalaModule
import javax.inject.Inject
object AkkaModule {
class ActorSystemProvider @Inject() (val injector: Injector) extends Provider[ActorSystem] {
override def get() = {
val system = ActorSystem("actor-system")
GuiceAkkaExtension(system).initialize(injector)
system
}
}
}
class AkkaModule extends AbstractModule with ScalaModule {
override def configure() {
bind[ActorSystem].toProvider[ActorSystemProvider].asEagerSingleton()
}
}
0を必要アクターシステムを注入する2つのクラス/オブジェクトであります
子供
import javax.inject.Inject
import akka.actor.{Actor, ActorRef, ActorSystem}
import com.google.inject.name.{Named, Names}
import com.google.inject.{AbstractModule, Provides, Singleton}
import net.codingwell.scalaguice.ScalaModule
class ServiceModule extends AbstractModule with ScalaModule with GuiceAkkaActorRefProvider {
override def configure() {
bind[Actor].annotatedWith(Names.named(ChildActorA.name)).to[ChildActorA]
bind[Actor].annotatedWith(Names.named(ChildActorB.name)).to[ChildActorB]
}
@Provides
@Named(ChildActorA.name)
def provideChildActorARef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, ChildActorA.name)
@Provides
@Named(ChildActorB.name)
def provideChildActorBRef(@Inject() system: ActorSystem): ActorRef = provideActorRef(system, ChildActorB.name)
}
延長
import akka.actor._
import com.google.inject.Injector
class GuiceAkkaExtensionImpl extends Extension {
private var injector: Injector = _
def initialize(injector: Injector) {
this.injector = injector
}
def props(actorName: String) = Props(classOf[GuiceActorProducer], injector, actorName)
}
object GuiceAkkaExtension extends ExtensionId[GuiceAkkaExtensionImpl] with ExtensionIdProvider {
override def lookup() = GuiceAkkaExtension
override def createExtension(system: ExtendedActorSystem) = new GuiceAkkaExtensionImpl
override def get(system: ActorSystem): GuiceAkkaExtensionImpl = super.get(system)
}
trait NamedActor {
def name: String
}
trait GuiceAkkaActorRefProvider {
def propsFor(system: ActorSystem, name: String) = GuiceAkkaExtension(system).props(name)
def provideActorRef(system: ActorSystem, name: String): ActorRef = system.actorOf(propsFor(system, name))
}
プロデューサー
import akka.actor.{IndirectActorProducer, Actor}
import com.google.inject.name.Names
import com.google.inject.{Key, Injector}
class GuiceActorProducer(val injector: Injector, val actorName: String) extends IndirectActorProducer {
override def actorClass = classOf[Actor]
override def produce() = injector.getBinding(Key.get(classOf[Actor], Names.named(actorName))).getProvider.get()
}
とあなたの俳優のためのプロバイダを作成するには、別の1
import javax.inject.Inject
import akka.actor._
object ParentActor {
def props(childName: String)(implicit @Inject() system: ActorSystem) = Props(classOf[ParentActor],system.actorOf(GuiceAkkaExtension(system).props(childName)))
}
class ParentActor (childActor: ActorRef) extends Actor {
def receive = {
case "Message" =>
println(s"ParentActor ${self.path} received message...")
childActor ! "Message"
}
}
object ChildActorA extends NamedActor{
override final val name = "ChildActorA"
def props() = Props(classOf[ChildActorA])
}
class ChildActorA extends Actor {
def receive = {
case "Message" =>
println("ChildActorA received message...")
}
}
object ChildActorB extends NamedActor{
override final val name = "ChildActorB"
def props() = Props(classOf[ChildActorB])
}
class ChildActorB extends Actor {
def receive = {
case "Message" =>
println("ChildActorB received message...")
}
}
あなたが明示的に子供に名前を付ける必要がありSBT
> run
[info] Running Bootstrap
ParentActor akka://actor-system/user/$b received message...
ParentActor akka://actor-system/user/$d received message...
ChildActorB received message...
ChildActorA received message...
[success] Total time: 1 s, completed Jun 14, 2016 1:23:59 AM
から
出力、
それは純粋なまたは最もエレガントな答えはありません、と私は、コードを最適化することができると確信していますが、それはあなたがすることができます同じ子と異なる子を持つインスタンスを作成します。
私はあなたにもBindingAnnotations
を使用することができることを考えているがあなたの代わりに '' ActorRef'のProps'を注入しようとしましたか? – Sergey
@Sergey少し詳しく説明できますか? – Nick
私は、「導入」と呼ばれるものを使用することで、ParentActorが適切な子アクターに「導入」されるという代替ソリューションがあると思います。たとえば、私のコントローラは、 "childActor"が適切な子アクタ(ChildActorAまたはChildActorBのいずれか)へのActorRefである "Message(childActor)"のようなParentActorにメッセージを送信します。 – Nick