当我引用类型化的 actor 系统时,如何为 AkkaStreams 实例化一个物化器?

How to instantiate a materializer for AkkaStreams when I have a reference to the typed actor system?

下面的代码无法编译,它表示 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()

2.6.x 的 Akka 文档表明 ActorMaterializer 已弃用:"Use the system wide materializer or Materializer.apply(actorContext) with stream attributes or configuration settings to change defaults."

改用这个:

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)
  }
}

此时 Akka Streams 需要一个“经典”(无类型)ActorSystem,它可以隐式转换为一个实体化器。

因此,如果在 Akka Typed Behavior 中具体化一个流,那么

implicit val materializer = context.classicActorContext.system

并且如果在 actor 之外实现一个流,但是你有一个类型 ActorSystem:

implicit val materializer = typedActorSystem.classicSystem

如@johanandren 所述,还可以将 Typed ActorSystem 置于隐式范围内,这将允许隐式转换为 Materializer 生效。

implicit val system = context.system

以前的答案是预期的新答案的一半API。

类型化的 ActorSystem 也可以隐式转换以提供系统实体化器,因此只需将其作为隐式提供就足够了。

例如:

Behaviors.setup { ctx =>
 implicit val system = ctx.system

 Source(1 to 10).runForeach(println)

 ...
}

其内部工作是从 Materializer 伴随对象中获得的隐式转换,它将 ClassicActorSystemProvider 的系统实体化器提取到 Materializer 中。类型化和经典 ActorSystem 实现都 ClassicActorSystemProvider.