从 Akka Streams 中传递的隐式 GraphBuilder 对象在哪里

Where is the implicit GraphBuilder object passed from in Akka Streams

正在学习Akka Streams库,有以下困惑。我看到一个隐式传递给 GraphDSL.create()(...) 调用的 Graphbuilder 对象。 我无法理解从哪里可以获取实际的构建器对象?

 val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
  import GraphDSL.Implicits._
  val in = Source(1 to 10)
  val out = Sink.ignore

  val bcast = builder.add(Broadcast[Int](2))
  val merge = builder.add(Merge[Int](2))

  val f1, f2, f3, f4 = Flow[Int].map(_ + 10)

  in ~> f1 ~> bcast ~> f2 ~> merge ~> f3 ~> out
  bcast ~> f4 ~> merge
  ClosedShape
})

builder 不是从外部隐式需要的。如果你看一下 create 函数的签名

def create[S <: Shape]()(buildBlock: GraphDSL.Builder[NotUsed] ⇒ S): Graph[S, NotUsed]

你会注意到它只需要一个从 BuilderShape 的函数。事实上,如果您从代码中删除 implicit 关键字,对 create 的调用应该仍然可以编译。

但是,您需要稍后在您的代码中使该构建器隐式可用,特别是当您需要 GraphDSL 符号时 ~>。如果你检查 ~>

的签名
def ~>[U >: T](to: Inlet[U])(implicit b: Builder[_]): Unit

你会看到这是需要隐式 Builder 的地方。这就是为什么 builder 参数需要注释为 implicit.

啊,看看源代码就更清楚了。 调用者传入函数,而构建器的实例化是从 create 函数内部完成的。

来自akka/stream/scaladsl/GraphApply.scala.template

def create[S <: Shape]()(buildBlock: GraphDSL.Builder[NotUsed] ⇒ S): Graph[S, NotUsed] = {
    val builder = new GraphDSL.Builder
    val s = buildBlock(builder)
    val mod = builder.module.replaceShape(s)

    new GraphApply.GraphImpl(s, mod)
  }