使用Google Guice

时间:2017-04-30 09:56:40

标签: scala dependency-injection guice

我正在尝试获取特征(接口)的所有实例子类。这个特性有多个实现,由第三方用户提供。

这是否可以在没有显式绑定的情况下获取所有实例子类,因为我没有控件,第三方用户提供了实现。 ?

我已经看到了你需要明确绑定的question

代码示例:

import javax.inject.Inject

import com.google.inject._

import scala.collection.JavaConversions._


object DemoApp extends App {
  val injector = Guice.createInjector(new AllImplModule)
  injector.getInstance(classOf[Action]).perform()


}

class Action @Inject()(impls: List[B]) {

  def perform() = {
    impls.foreach(b => println(b.name))
  }

}

class AllImplModule extends AbstractModule {
  override def configure() = {
    bind(classOf[Action]).asEagerSingleton()
  }

  @Provides
  @Singleton
  def getAllImpls(injector: Injector): List[B] = {
    injector.getAllBindings().keySet().collect {
      case key: Key[_] if (classOf[B].isAssignableFrom(key.getTypeLiteral().getRawType())) =>
        injector.getInstance(key).asInstanceOf[B]
    }.toList

  }
}

trait B {
  def name: String
}

class C1 extends B {
  override def name: String = "C1"

}


class C2 extends B {
  override def name: String = "C2"
}

这不起作用。任何帮助,将不胜感激!

2 个答案:

答案 0 :(得分:1)

您可以使用guice-multibindings扩展名注入多个特征实现。

"com.google.inject.extensions" % "guice-multibindings" % "4.1.0"添加到build.sbt文件

在Play模块中定义您的绑定:

 val multipleBinder = Multibinder.newSetBinder(binder(),classOf[BaseTrait])
 multipleBinder.addBinding().to(classOf[Implementation1])
 multipleBinder.addBinding().to(classOf[Implementation2])

在要注入多个绑定的组件中,以这种方式声明依赖项:

baseTraits: java.util.Set[BaseTrait]

然后它应该工作。

答案 1 :(得分:1)

您的示例代码看起来不错。这是一个Scala工作表,可动态查找某个abstract class / trait

的所有绑定实现
import com.google.inject.{AbstractModule, Guice}
import scala.collection.JavaConverters._

trait Foo {
    def name: String
}
class Foo1 extends Foo {
    override def name = "Foo1"
}
class Foo2 extends Foo {
    override def name = "Foo2"
}

val testModule = new AbstractModule {
    override def configure(): Unit = {
        bind(classOf[Foo1]).toInstance(new Foo1)
        bind(classOf[Foo2]).toInstance(new Foo2)
        bind(classOf[Int]).toInstance(42)
    }
}

val injector = Guice.createInjector(testModule)

private def bindingsFor[T](c: Class[T]): Iterable[T] = injector.getAllBindings.asScala.keys
    .filter { key ⇒ c.isAssignableFrom(key.getTypeLiteral.getRawType) }
    .map { key ⇒ injector.getInstance(key).asInstanceOf[T] }

bindingsFor(classOf[Foo]).map(_.name).mkString(", ")

返回:

output: String = Foo1, Foo2