我想实现一个Guice模块,它将一个适配器绑定到一个命名参数,但是为了创建这个适配器,它需要实例化另一个类,它也需要注入参数。
以下是Scala中的示例:
trait Service
class UserService @Inject()(@Named(value = "foo") foo: String) extends Service
trait Adapter
class AdapterImpl(service: Service) extends Adapter
class AdapterRef(val adapter: Adapter)
class Module extends AbstractModule {
override def configure(): Unit = {
val fooValue = "bar"
bind(classOf[String])
.annotatedWith(Names.named("foo"))
.toInstance(fooValue)
val userService = new UserService(fooValue) //It should be instantiated by Guice somehow
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toInstance(new AdapterRef(new AdapterImpl(userService))) //Thats kinda ok
}
}
有人能指出我正确的方向吗?
谢谢,
的Gabor
答案 0 :(得分:0)
您可以在模块中使用Provides方法,这样您就可以删除绑定。这是我在Scala的最大努力,所以如果语法不正确,请告诉我。
@Provides() @Singleton() def provideAdapterRef(service: Service): AdapterRef = {
return new AdapterRef(new AdapterImpl(service))
}
请注意使用Singleton模仿您使用toInstance
的示例。如果您不需要它始终提供相同的实例,我建议您删除范围并让它每次都创建一个新范围。
另一种解决方案是使用Provider。这要求您在模块中保留绑定的修改版本并创建一个额外的类,但如果您的提供程序更复杂,它可以是更清晰的解决方案。
//Can inject UserService as well, or provide annotations to configure which
//implementation of Service you get if you have more than one.
class UserServiceProvider @Inject()(service: Service) extends Provider[AdapterRef] {
override def get(): AdapterRef {
return new AdapterRef(new AdapterImpl(service))
}
}
然后您可以将模块中的绑定更改为
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toProvider(classOf[UserServiceProvider])
.in(classOf[Singleton])
此处请注意使用in(Singleton)
复制您的toInstance
行为。