管理Guice的复杂生命周期

时间:2016-09-12 03:45:30

标签: java dependency-injection guice assisted-inject

我遇到过我有数据对象图的情况,并希望为此图上的每个节点创建一个服务。问题是这个服务(及其依赖关系)依赖于他们正在为之工作的节点。像这样:

class Visitor {

  void enter(Node node){
    Service service = guice.create(node)

    service.doComplexDomainLogic(/*some runtime information about the graph and the path to get here, other things*/)
  }
}

请注意,我的目的是为图表中的每个节点创建Service new 实例,以及Service的任何依赖项的新实例。< / p>

所以现在我有几个选择:

  • guice由辅助注射工厂提供支持。这就是我们目前正在做的事情,如果它们依赖于node,则要求所有服务依赖于对节点的依赖 curry 。换句话说,如果我在这里使用辅助注射工厂,我必须为service依赖的每个类使用它,这是令人讨厌的。
  • 我可以使用我们称之为嵌套bootstrappers ,即带有新注入器的新模块,实际上是一个新环境,并且在该环境的设置中我可以编写bind(Node.class).toInstance(node)。此代码将在第一次访问时执行,并将其结果缓存。
  • 我可以使用guice的自定义范围(我认为)。

我们在几个地方完成了第二次,仅仅因为我和我的团队都不了解自定义范围。我们现在有一个自定义范围的另一个用途,我必须承认它实现起来要比我想要的复杂得多。在this guide之后有所帮助,但很明显我将不得不重新回到安全的土地上,而我上次的访问并不那么令人愉快。

我应该使用什么guice工具来解决这个问题?

1 个答案:

答案 0 :(得分:2)

您可以为所需的片段注入Injectorcreate a child injector。子注入器将允许您修改对象图并访问所有父注入器的依赖项,但您可以像您一样深入访问您的节点。

class Visitor {
  @Inject Injector injector;

  void enter(final Node node) {
    Service service = injector.createChildInjector(new AbstractModule() {
      @Override public void configure() {
        bind(Node.class).toInstance(node);
        // Anything that does require a Node should be bound here, because
        // you can't define it in the parent due to the unsatisfied binding.
        bind(SomeInterface.class).to(SomeClassThatRequiresNode.class);
      }
    }).getInstance(Service.class);

    service.doComplexDomainLogic(/* ... */)
  }
}

尽管可以使用范围执行类似的操作,但请记住,范围仅用于标识when to create a new object versus when to return the same object。这意味着您可以创建@NodeScoped范围并确保在处理给定节点时返回相同的对象,但您仍需要绑定某种@NodeScoped NodeHolder以在潜水时保留节点in。而不是保留和填充这个单独的持有者,子进样器将允许您直接请求节点,这可以使您的代码更容易理解和测试。

另见: