如何在guice-like过滤器中连接N个节点链

如何在guice-like过滤器中连接N个节点链,guice,guice-3,Guice,Guice 3,我想创建节点A(多路复用器),它有N个节点B。每个节点B有它自己的节点C,每个节点C有它自己的节点D,每个节点D有它自己的节点E 假设A的B,C,D,E链的个数N=4。理想情况下,每个节点E以i=0、1、2、3之类的信息结束 除此之外,我可能想重新排序B、C、D,因为它们非常类似于过滤器,所以我让它们都实现了一个与 Response service(Request r); 我非常想远离辅助注入,因为新来的开发人员总是会被它弄糊涂(至少我已经注意到了这一点,并且厌倦了教它,我也认为它有点难看和混

我想创建节点A(多路复用器),它有N个节点B。每个节点B有它自己的节点C,每个节点C有它自己的节点D,每个节点D有它自己的节点E

假设A的B,C,D,E链的个数N=4。理想情况下,每个节点E以i=0、1、2、3之类的信息结束

除此之外,我可能想重新排序B、C、D,因为它们非常类似于过滤器,所以我让它们都实现了一个与

Response service(Request r);
我非常想远离辅助注入,因为新来的开发人员总是会被它弄糊涂(至少我已经注意到了这一点,并且厌倦了教它,我也认为它有点难看和混乱)。他们似乎不需要在所有其他方面进行培训,这样就很容易了

我在想也许我只是注入了一个提供者,B有一个C,C有一个D,然后他们都有启动方法,但这并不像我希望的那样,因为启动方法必须在每个服务上改变,并且他们的启动方法必须匹配。看,问题是节点A有关于节点编号E的信息,需要将该信息发送给E,但B、C和D不需要该信息

我可以在A构造器中进行一些布线,然后

Provider<B> bProvider
Provider<E> eProvider
Provider-bProvider
提供者eProvider
但是,我怎样才能把E从链条上拉下来呢。我不太确定是否有一个干净的方法来做这一切

谢谢,
迪安

我可以想出三种方法:儿童注射器、手动DI和辅助注射

儿童注射器 这可能是最好的选择,也列出了

根据上的Guice文档中的提示,您可以创建一个子注入器,该注入器允许您的
@NodeNumber int
绑定到树中您想要的任何位置。这意味着您的绑定和结构不必做太多更改,即使过滤器顺序发生了更改,或者以后在C、D、F或其任何依赖项中需要您的节点号。B、 在您提供节点枚举器绑定之前,C、D和E都是不可注入的,但这对于您所描述的可能是正确的

当然,您可以使用
@Named(“nodeNumber”)
而不是定义
@nodeNumber
,也可以重构为保存在其他地方的BFactory

class E {
  @Inject @NodeNumber int nodeNumber;  // Available anywhere in your graph!
}
class D { @Inject E e; }
class C { @Inject D d; }
class B { @Inject C c; }
class A {
  @Inject Injector injector;  // You can always inject the Injector!
  B addNode(final int nodeNumber) {
    // Create a new injector
    return injector.createChildInjector(new AbstractModule() {
      @Override public void configure() {
        bindConstant().annotatedWith(NodeNumber.class).to(nodeNumber);
      }
    }).getInstance(B.class);
  }
}
手动DI 如果只有少数几个不经常更改的依赖项,则可以手动创建自己的堆栈。这可能不会充分利用Guice的潜力,但很清楚这里发生了什么,如果B/C/D/E获得或失去任何DEP,需要改变什么

class A {
  @Inject Provider<SomeDepOfB> bDep;  // If anything in the tree has other deps,
  @Inject Provider<SomeDepOfC> cDep;  // you'll need to provide them yourself.
  @Inject Provider<SomeDepOfD> dDep;

  B addNode(int nextNodeNumber) {
    return new B(
        bDep.get(),
        new C(
            cDep.get(),
            new D(
                dDep.get(),
                new E(nextNodeNumber))));
  }
}

虽然辅助注射在这里可能不是正确的选择,但它的使用非常简单,而且它可以带走很多样板文件(特别是如果E有很多其他DEP等)。

如果a有一些B,B有一些C等,一直到E,那么它们不是真正的过滤器,你不能改变顺序。如果你想让过滤器重新排序,那么在某个地方有一个设计缺陷。@durron597好吧,我们可能会在链中添加更多的“过滤器”,顺序可能会很重要,但有时它们被放在错误的顺序中,出于这样或那样的原因,当有人遇到一些奇怪的错误时,我们可能想重新排序…我知道这实际上是最近发生的。你误解了我。A有B,B有C,C有D等等。听起来像是类层次结构中的字段。每个级别都是一个过滤器,听起来更像是一个列表。很抱歉,如果没有实际的代码来参考,这很难解释,也许你可以包含更多的代码。我刚刚使用了childInjector解决方案,它最终是最好的,非常棒。我过去使用的另一个解决方案是简化每个人都有一个开始(配置)方法,这样您就可以创建应用程序,然后调用start(并在每个子对象上调用for循环start)。这使它保持了相当干净,并且在每个支腿只是不同配置的情况下,不需要儿童注射器解决方案。
class E {
  interface Factory { E create(int nodeNumber); }
  E(@Assisted int nodeNumber, SomeDep1OfE dep1, SomeDep2OfE dep2) { /* ... */ }
}

class D {
  interface Factory { D create(int nodeNumber); }
  D(@Assisted int nodeNumber, E.Factory eFactory) { /* ... */ }
}

// ...

class YourModule extends AbstractModule {
  @Override public void configure() {
    install(new FactoryModuleBuilder().build(E.Factory.class));  // Binds E.Factory
  }
}