我有一个WebSocket
控制器,它创建每个连接actor处理程序:
class WebSocketController @Inject()(cc: ControllerComponents)(implicit exc: ExecutionContext) {
def socket: WebSocket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlow.actorRef { out => // Flow that is handled by an actor from 'out' ref
WebSocketActor.props(out) // Create an actor for new connected WebSocket
}
}
}
在actor处理程序中我需要使用ReactiveMongo
:
trait ModelDAO extends MongoController with ReactiveMongoComponents {
val collectionName: String
...
}
class UsersCollection @Inject()(val cc: ControllerComponents,
val reactiveMongoApi: ReactiveMongoApi,
val executionContext: ExecutionContext,
val materializer: Materializer)
extends AbstractController(cc) with ModelDAO {
val collectionName: String = "users"
}
因此,通常的方法是在目标类中使用@Inject()UsersCollection
。但我无法做到这样的事情:
class WebSocketActor @Inject()(out: ActorRef, users: UsersCollection) extends Actor { ... }
因为actor的实例在WebSocketActor
个伴随对象中创建:
object WebSocketActor {
def props(out: ActorRef) = Props(new WebSocketActor(out))
}
如何在UsersCollection
内使用WebSocketActor
?
答案 0 :(得分:1)
您可以创建演员,Play会自动注入依赖项。没问题。 (https://www.playframework.com/documentation/2.6.x/ScalaAkka)
但如果是网络套接字,则需要演员的道具,而不是演员(或演员参考)本身。
ActorFlow.actorRef { out => // Flow that is handled by an actor from 'out' ref
WebSocketActor.props(out) // <- ACTOR IS NOT CREATED HERE, WE RETURN PROPS
}
所以在这种情况下没有办法自动完成(至少我没有找到它)。
您可以做的是手动传递UsersCollection
。
class WebSocketController @Inject()(cc: ControllerComponents, usersCollection: UsersCollection)(implicit exc: ExecutionContext) {
def socket: WebSocket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlow.actorRef { out => // Flow that is handled by an actor from 'out' ref
WebSocketActor.props(out, usersCollection) //<- ACTOR IS NOT CREATED HERE, WE RETURN PROPS
}
}
}
注意到我已将UsersCollection
注入WebSocketController
并将其传递给道具。
简单,我认为没有任何不利之处。
答案 1 :(得分:0)
我的Play应用程序中有一个事件处理程序模块,它基本上在应用程序启动时实例化所有actor。事件处理程序都是演员,所以你可以这样做:
class EventHandlerBootstrap @Inject() (system: ActorSystem, app: Application) {
EventHandlerBootstrap.handlers.foreach {
case (h, n) => system.actorOf(Props(app.injector.instanceOf(h)), n)
}
}
//These Class[_ <: EventHandler] are classes of user defined actors each with their own
// dependencies which guice will take care of automattically.
object EventHandlerBootstrap {
val handlers: Map[Class[_ <: EventHandler], String] = Map(
classOf[UserRegisteredHandler] -> "user-registered-handler",
classOf[CustomerOrderCreatedHandler] -> "customer-order-created-handler",
classOf[DisputeClosedHandler] -> "dispute-closed-handler",
classOf[Throttle] -> "throttle"
)
}
在模块内部我运行这样的引导程序:
class EventModule extends ScalaModule with AkkaGuiceSupport {
override def configure(): Unit = {
bind[EventHandlerBootstrap].asEagerSingleton()
}
}
如果你当然不急于盲目遵循我的食谱,你仍然可以看出注入你的演员及其依赖关系的事实完全由guice支持,如上所示。希望它能帮助