ScalaでSPI(サービスプロバイダインターフェース)を使う

Scalaでも、JavaのSPI(サービスプロバイダインターフェース)はもちろん使えます。

SPIは、AsakusaFrameworkで知って、Javaではいろいろ遊んでみたのですが、Scalaでは試してなかったので、試してみました。

ソースはこちら。
https://github.com/rabitarochan/scala-spi-test.git

インターフェースは?

Javaでは、インターフェースの実装クラスを [ META-INF/services/${インターフェースのFQCN} ] というファイルに書きます。

Scalaでは、インターフェース名の部分をトレイト名にしてあげることで、同じように使えました。

呼び出し方

ほぼJavaと同様ですが、Service.providers で得られるIteratorジェネリクスでないため、キャストが必要なようです。

package com.rabitarochan.parent

import java.util.Iterator
import scala.collection.JavaConversions._
import sun.misc.Service

object Main extends App {
  val services = Service.providers(classOf[PrintTrait]).asInstanceOf[Iterator[PrintTrait]]

  val message = "Hello world"

  services.foreach(p => p.print(message))

}

Scala版SPI?

github内を[ META-INF/services ]で検索してみたところ、apache/activemq-apolloというプロジェクトで[ ClassFinder ]というソースを見つけました。

https://github.com/apache/activemq-apollo/blob/5b8879cd8a681bcd91c5b661d26ccd51783bd06b/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala

SPIの内部もこのような実装になってるのかなと思いつつ、他にも同じようなものがないかをいろいろ探しています。