【问题标题】:Chaining assisted injected parameters using guice-assistedinject使用 guice-assistedinject 链接辅助注入参数
【发布时间】:2014-03-04 03:16:04
【问题描述】:

我正在使用 Guice Assisted Inject 库为我建立一个工厂。我目前的设置是这样的:

class MyObject {
  @Inject public MyObject(@Assisted FirstDep first, @Assisted SecondDep second, ThirdDep third) { /**/ }
}

class FirstDep { /* nothing to see here */ }
class SecondDep {
  @Inject public SecondDep(@Assisted FirstDep first) { /**/ }
}
class ThirdDep { /* nothing to see here either */ }

class MyModule extends AbstractModule {
  @Override public void configure() {
    bind(ThirdDep.class);
    install(new FactoryModuleBuilder().build(MyObjectFactory.class));
  }
}

interface MyObjectFactory {
  SecondDep createSecond(@Assisted FirstDep first);
  MyObject createMyObject(@Assisted FirstDep first, @Assisted SecondDep second);
}

这迫使我使用factory.createController(first, factory.createSecond(first)) 显式创建SecondDep。是否可以更改我的绑定,以便我可以简单地执行factory.createController(first),它会自动使用SecondDep 绑定和我传入的参数?

【问题讨论】:

  • 我已经尝试使用方法 MyObject createMyObject(@Assisted FirstDep first) 使 MyFactory 成为一个抽象类,该方法包装了两个生成的方法,但这不起作用。 Guice 要求工厂类型是接口。

标签: java guice assisted-inject


【解决方案1】:

考虑您在此处创建的 API,尤其是关于未来的扩展或实现。显然,您周围有许多有状态的 FirstDep 实例,因为 SecondDep 依赖于特定的 FirstDep,但未来的 SecondDep 可能不依赖于同一个 FirstDep(或任何 FirstDep)。 createMyObject(first) 可以是 createMyObject(first, factory.createSecond(first)) 的简写这一事实是特定于您的业务案例的,我认为 Guice 中没有简写来做出这种假设。

也就是说,您有两个选择。一、你可以创建一个非常小的助手:

// Encapsulate the createMyObject(first) shorthand.
class MyObjectHelper {
  @Inject MyObjectFactory rawFactory;

  MyObject createMyObject(FirstDep first) {
    return rawFactory.createMyObject(first, rawFactory.createSecond(first));
  }
}

或者,两个,您可以使用@AssistedInject 让 Guice 有效地重载构造函数:

class MyObject {
  // Multiple @AssistedInject constructors, selected based on which parameters
  // are marked with @Assisted.

  @AssistedInject public MyObject(@Assisted FirstDep first,
       SecondFactory secondFactory, ThirdDep third) {
    this(first, secondFactory.createSecond(first), third);
  }

  @AssistedInject public MyObject(@Assisted FirstDep first,
      @Assisted SecondDep second, ThirdDep third) { /**/ }
}

interface SecondFactory {
  // Note that @Assisted annotations are not needed here. Every parameter in
  // these interfaces is for assisted injection, by definition.
  SecondDep createSecond(FirstDep first);
}

interface MyObjectFactory {
  MyObject createMyObject(FirstDep first);
  MyObject createMyObject(FirstDep first, SecondDep second);
}

虽然为每个类创建一个单独的工厂稍微有点冗长,但我认为您会发现它有助于使您的类/工厂保持独立且易于遵循,并且它巧妙地避免了潜在的循环引用如果Guice支持,我不记得了。我倾向于将我的工厂暴露为嵌套接口:

class SecondDep {
  interface Factory {
    SecondDep create(FirstDep first);
  }

  @Inject public SecondDep(@Assisted FirstDep first) { /**/ }
}

...然后,您可以找到并更新与它支持的类完全相邻的Second.Factory

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多