在Guice中管理复杂生命周期



我遇到了这样一种情况,我有一个数据对象图,并且希望为这个图上的每个节点创建一个服务。问题是此服务(及其依赖项)依赖于它们所工作的节点。像这样:

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

我们在几个地方做了第二种,仅仅是因为我和我的团队不知道自定义作用域。现在我们有了自定义作用域的另一种用法,我必须承认它的实现比我希望的要复杂得多。下面的指南会有所帮助,但很明显,我将不得不回到安全的地方,我上次的访问并不那么愉快。

我应该使用什么指导工具来获得此行为?

你可以注入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来保存您的节点。子注入器可以让你直接请求一个Node,而不是保留和填充这个单独的holder,这可能会让你的代码更容易理解和测试。

参见:

  • 向导辅助注入
  • 如何在过滤器等向导中连接N个节点链

相关内容

  • 没有找到相关文章

最新更新