如何在Play 2.4中创建一个Actor,以便它使用Guice自动注入依赖项?我读了几篇文章,他们使用了GuiceApplicationBuilder,然后创建了actor。我不想控制实例化播放应用程序的方式。相反,我只想知道如何创建一个actor实例,以便使用Guice管理依赖项。
创建一个包含5名工作人员的RoundRobinRouter
class RouterActor extends Actor with ActorLogging {
val router = {
val routees = Vector.fill(5) {
val r = context.actorOf(Props[Worker])
context watch r
ActorRefRoutee(r)
}
Router(RoundRobinRoutingLogic(), routees)
}
def receive = {
case job: Job =>
router.route(job, sender())
}
}
扩展AkkaGuiceSupport并创建一个绑定了RouterActor的模块
class RouterActorModule extends AbstractModule with AkkaGuiceSupport {
override def configure() = {
bindActor[RouterActor]("router-manager")
}
}
根据RouterModule中actor的名称,使用guice DI注入RouterActor
class ScheduledReportGenerationService @Inject() (@Named("router-manager") serviceRouter: ActorRef) extends Actor {
def receive = {
case serviceInfo: ServiceContext => submitJobs(serviceInfo)
}
def submitJobs(serviceInfo: ServiceContext) = {
serviceRouter ? serviceInfo
}
}
如何初始化ScheduledReportGenerationService actor以便Guice自动注入RouterActor?我收到以下错误
java.lang.IllegalArgumentException: no matching constructor found on class vistoscheduler.ScheduledReportGenerationService for arguments []
我理解system.actorOf使用Akka来创建Actor,因此Guice无法注入依赖项。文档不是很清楚,我无法解决这个问题。
class SchedulerBootStrap extends Actor {
implicit val system = context.system
implicit val timeout = Timeout(5.minute)
def receive = {
case "BOOTSTRAP_SCHEDULER" => bootStrapServices()
}
def bootStrapServices() = {
lazy val scheduledReportGenerationService = system.actorOf(Props[ScheduledReportGenerationService], "scheduled-reports-service-actor")
scheduledReportGenerationService ? ServiceContext(1L)
}
}
答案 0 :(得分:1)
您可以使用IndirectActorProducer
,
class GuiceActorProducer(val injector: play.inject.Injector, val cls: Class[_ <: Actor]) extends IndirectActorProducer {
override def actorClass = classOf[Actor]
override def produce() = {
injector.instanceOf(cls)
}
}
并创建您的服务,
val scheduledReportGenerationService = system.actorOf(Props(classOf[GuiceActorProducer], injector, classOf[ScheduledReportGenerationService]))
请确保您使用的是play.inject.Injector
。
编辑以使用com.google.inject.Injector
添加工作代码 。
class Application @Inject() (injector: Injector, system: ActorSystem) extends Controller {
def index = Action { request =>
val scheduledReportGenerationService = system.actorOf(Props(classOf[GuiceActorProducer], injector, classOf[ScheduledReportGenerationService]))
scheduledReportGenerationService ! "some"
Ok(views.html.index("Your new application is ready."))
}
}
class RouterActor extends Actor with ActorLogging {
def receive = {
case x: String =>
log.info(x)
}
}
class ScheduledReportGenerationService @Inject() (@Named("router-manager") serviceRouter: ActorRef) extends Actor {
implicit val timeout = Timeout(5.minute)
def receive = {
case serviceInfo: String => submitJobs(serviceInfo)
}
def submitJobs(serviceInfo: String) = {
log.info("service")
serviceRouter ? serviceInfo
}
}
class RouterActorModule extends AbstractModule with AkkaGuiceSupport {
override def configure() = {
bindActor[RouterActor]("router-manager")
}
}
class GuiceActorProducer(val injector: Injector, val cls: Class[_ <: Actor]) extends IndirectActorProducer {
override def actorClass = cls
override def produce() = {
injector.getInstance(cls)
}
}
使用akka Extension
还有另一种方法可以做到这一点。请参阅this project。