Get All the instance subclass of trait using Google Guice

依然范特西╮ 提交于 2019-12-08 03:30:14

问题


I am trying to get All the instances subclass of trait(interface). This trait have multiple implementation which are provided third party users.

Is this possible to get All the instances subclasses without explicit binding because I don't have control, Implementation provided by third party users. ?

I already saw the same question in which you need to bind explicitly.

Code sample:

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

This is not working. Any help would be appreciated!


回答1:


You can inject multiple implementations of the trait using guice-multibindings extension.

Add "com.google.inject.extensions" % "guice-multibindings" % "4.1.0" to your build.sbt file

In the Play module define your bindings like this:

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

In the component when you want to inject your multiple bindings declare the dependency in this way:

baseTraits: java.util.Set[BaseTrait]

Then it should work.




回答2:


Your example code looks ok. Here is a Scala worksheet that dynamically finds all bound implementations of a certain 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(", ")

Returns:

output: String = Foo1, Foo2


来源:https://stackoverflow.com/questions/43705146/get-all-the-instance-subclass-of-trait-using-google-guice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!