1

我遇到了一种情况,我有一个数据对象图,并且想为该图上的每个节点创建一个服务。问题是该服务(及其依赖项)依赖于他们正在工作的节点。像这样的东西:

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和任何依赖项的新实例。Service

所以现在我有几个选择:

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

我们在几个地方完成了第二个,只是因为我和我的团队不知道自定义范围。我们现在有了自定义作用域的另一种用途,我必须承认它的实现比我想的要复杂得多。遵循本指南会有所帮助,但很明显,我将不得不深入研究线程安全的土地,而我最后一次访问那里并不那么愉快。

我应该使用什么 guice 工具来获得这种行为?

4

1 回答 1

2

您可以注入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(/* ... */)
  }
}

尽管可以对范围做类似的事情,但请记住,范围仅用于确定何时创建新对象以及何时返回相同的对象。这意味着您可以创建一个@NodeScoped范围并确保在处理给定节点时返回相同的对象,但是您仍然需要绑定某种类型的对象@NodeScoped NodeHolder来保存您的节点。而不是保存和填充这个单独的持有者,子注入器会让你直接请求一个节点,这可能会让你的代码更容易理解和测试。

也可以看看:

于 2016-09-12T16:56:45.593 回答