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

有人可以指出我正确的方向吗?

谢谢

加博尔

可以在模块中使用 Provision 方法,该方法允许您删除绑定。这是我在 Scala 所做的最大努力,所以如果语法不正确,请告诉我。

@Provides() @Singleton() def provideAdapterRef(service: Service): AdapterRef = {
    return new AdapterRef(new AdapterImpl(service))
}

请注意使用单例来模仿您的示例使用toInstance。如果您不需要它始终提供相同的实例,我建议您删除范围并让它每次创建一个新范围。

另一种解决方案是使用提供程序。这要求您在模块中保留绑定的修改版本并创建一个额外的类,但如果提供程序更复杂,这可能是一个更干净的解决方案。

//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行为。

相关内容

  • 没有找到相关文章

最新更新