【问题标题】:How to instantiate a materializer for AkkaStreams when I have a reference to the typed actor system?当我引用类型化的 Actor 系统时,如何为 AkkaStreams 实例化一个物化器?
【发布时间】:2020-05-28 22:10:34
【问题描述】:
下面的代码无法编译,它表示 ActorMaterializer 缺少一个隐式 ActorRefFactory。我应该如何提供?
val guardian: Behavior[Done] = Behaviors.setup(_ => {
Behaviors.receiveMessage{
case Done => Behaviors.stopped
}
})
implicit val sys = ActorSystem(guardian, "sys")
implicit val materializer: Materializer = ActorMaterializer()
【问题讨论】:
标签:
scala
akka
akka-stream
akka-typed
【解决方案1】:
2.6.x 的 Akka 文档表明 ActorMaterializer 已被弃用:“使用系统范围的 Materializer 或 Materializer.apply(actorContext) 以及流属性或配置设置来更改默认值。”
改用这个:
import akka.Done
import akka.actor.ActorSystem
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import akka.stream.Materializer
object Main {
def main(Args: Array[String]) : Unit = {
val guardian: Behavior[Done] = Behaviors.setup(_ => {
Behaviors.receiveMessage{
case Done => Behaviors.stopped
}
})
val as = ActorSystem()
val materializer = Materializer(as)
}
}
【解决方案2】:
此时,Akka Streams 需要一个“经典”(无类型)ActorSystem,它可以隐式转换为物化器。
因此,如果在 Akka Typed Behavior 中实现流,则可以
implicit val materializer = context.classicActorContext.system
如果在演员之外实现流,但您输入了ActorSystem:
implicit val materializer = typedActorSystem.classicSystem
正如@johanandren 所提到的,也可以将Typed ActorSystem 放在隐式范围内,这将使隐式转换为Materializer 生效。
implicit val system = context.system
【解决方案3】:
以前的答案是新 API 的一半。
类型化的ActorSystem 也可以隐式转换以提供系统物化器,因此只需将其作为隐式提供就足够了。
例如:
Behaviors.setup { ctx =>
implicit val system = ctx.system
Source(1 to 10).runForeach(println)
...
}
其内部工作是从Materializer 伴随对象中获得的隐式转换,它将ClassicActorSystemProvider 的系统物化器提取到Materializer。类型化的和经典的ActorSystem 都实现了ClassicActorSystemProvider。