我有一个类PluginManager
,它使用Guice多重绑定功能接受Set<Plugin>
。但是,PluginManager
有一些运行时信息需要传递给Plugin
构造函数。
这似乎是Guice辅助注入的完美用例,即我的PluginManager
将注入Set<PluginFactory>
,其中运行时信息被提供给每个工厂,从而产生所需的{{1}实例。
但我不知道Plugin
中使用的语法。多重绑定器Module
似乎无法连接addBinding
的结果。
我可以创建自己的自定义Factory实现和多绑定,但是有没有办法将multibinder和辅助注入结合起来?
答案 0 :(得分:2)
我认为这可以为您提供一个完全符合您需求的示例。请注意,scala的multibinder有一个挂起的pull请求,允许您在多个位置创建set binder。
object Test {
trait Plugin {
def name(): String
}
object Plugin {
trait Factory[+T <: Plugin] {
def newPlugin(name: String): T
}
}
case class MyPlugin @Inject() (@Assisted name: String) extends Plugin
case class OtherPlugin @Inject() (@Assisted name: String) extends Plugin
class PluginManager @Inject() (pluginFactories: Set[Plugin.Factory[Plugin]]) {
for (factory <- pluginFactories) {
println(factory.newPlugin("assisted injection"))
}
}
def main(args: Array[String]): Unit = {
val injector = Guice.createInjector(new ScalaModule {
override def configure(): Unit = {
val plugins = ScalaMultibinder.newSetBinder[Plugin.Factory[Plugin]](binder)
plugins.addBinding().to[Plugin.Factory[MyPlugin]]
plugins.addBinding().to[Plugin.Factory[OtherPlugin]]
bindFactory[Plugin, MyPlugin, Plugin.Factory[MyPlugin]]()
bindFactory[Plugin, OtherPlugin, Plugin.Factory[OtherPlugin]]()
bind[PluginManager].asEagerSingleton()
}
def bindFactory[I: Manifest, C <: I : Manifest, F: Manifest](): Unit = {
import net.codingwell.scalaguice._
install(new FactoryModuleBuilder()
.implement(typeLiteral[I], typeLiteral[C])
.build(typeLiteral[F]))
}
})
}
}
根据您想要的风格,您可以做很多事情。例如,您可以制作一个通用的addPlugin方法(当发布更新版本的scala-guice时),如下所示:
val injector = Guice.createInjector(new ScalaModule {
override def configure(): Unit = {
bindPlugin[MyPlugin]()
bindPlugin[OtherPlugin]()
bind[PluginManager].asEagerSingleton()
}
def bindPlugin[T <: Plugin : Manifest](): Unit = {
val plugins = ScalaMultibinder.newSetBinder[Plugin.Factory[T]](binder)
plugins.addBinding().to[Plugin.Factory[T]]
bindFactory[Plugin, T, Plugin.Factory[T]]()
}
def bindFactory[I: Manifest, C <: I : Manifest, F: Manifest](): Unit = {
import net.codingwell.scalaguice._
install(new FactoryModuleBuilder()
.implement(typeLiteral[I], typeLiteral[C])
.build(typeLiteral[F]))
}
})