Guice绑定一个类及其适配器

时间:2017-05-29 16:04:20

标签: scala dependency-injection guice

我想实现一个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

1 个答案:

答案 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行为。