#scala #dependency-injection #akka
#scala #внедрение зависимостей #akka
Вопрос:
Я новичок в внедрении зависимостей, и теперь, когда я перенес свое приложение на Play 2.5.x, мне нужно учиться.
У меня есть одноэлементный сервис, который выглядит примерно так:
import javax.inject._
@Singleton
class WorkerService {
def doWork(work:String) {
...
}
}
У меня есть актер, который выглядит примерно так:
import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
import akka.actor._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import scalaj.http._
import WorkerService
object PollActor {
def props(host: String) = Props(new PollActionActor(host))
}
// Actor that polls a host for information
class PollActor(host: String) extends Actor with ActorLogging {
// timer for poll
var timer: Cancellable = context.system.scheduler.schedule(0 second, 10 second, self, TimeStep())
// handle messages
override def receive = {
case TimeStep() =>
getWork match {
case Some(work:String) =>
// How to do this?: ChecklistService.doWork(work)
case None =>
}
}
def getWork = {
try {
Some(Http(host)
.option(HttpOptions.readTimeout(10000))
.option(HttpOptions.connTimeout(10000))
.asString.body)
} catch {
case _:Throwable =>
None
}
}
case class TimeStep()
}
И контроллер что-то вроде этого:
@Singleton
class Application @Inject() (implicit system: ActorSystem) extends Controller {
val pollActor = system.actorOf(PollActor.props("127.0.0.1"))
def index = Action {
pollActor ! TimeStep
}
}
Как я могу вызвать WorkerService.doWork
временной шаг актера?
Ответ №1:
Вероятно, вам не следует создавать актера в классе Application.
Попробуйте использовать модуль для создания своего актера следующим образом
class ApplicationConfigModule extends AbstractModule with AkkaGuiceSupport {
override def configure(): Unit = {
bindActor[PollActor]("poll-actor")
}
}
в вашем resources/application.conf поместите это
play.modules.enabled = "com.nowtv.platform.search.module.ApplicationConfigModule"
Затем внедрите сервис в свой актер
class PollActor @Inject()(WorkerService: workerService) extends Actor
И внедрите актера в свой контроллер, чтобы вы могли использовать его там
@Singleton
class Application @Inject() (@Named("poll-actor") pollActor: ActorRef) extends Controller {
Комментарии:
1. Спасибо, я попробую это, как только мое приложение сможет снова что-то запустить, эта миграция — огромная боль.
2. Хорошо, похоже, это работает для актеров, у которых нет параметров в конструкции, но это не работает:
object PollActor { def props(out: ActorRef) = Props(new PollActor(out)) } class PollActor @Inject()(WorkerService: workerService)(host: String) extends Actor { ... }
3. Я попробовал это, и это сработало, но моему приложению стало очень сложно следовать, поэтому я вернулся к одноэлементным шаблонам Scalas и инициировал их из класса Application с введенными параметрами. Создание приложения с нуля было бы другим делом. Спасибо!