如何连接像过滤器这样的guice中的N个节点链 [英] How can I wire up N chains of nodes in guice like filters

查看:96
本文介绍了如何连接像过滤器这样的guice中的N个节点链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to create node A(multiplexor) which has N node B's. Each node B has it's own node C and each node C has it's own node D and each node D has it's own node E.

比方说,A拥有的B,C,D,E链的数量为N = 4.理想情况下,每个节点E都以i = 0、1、2、3之类的信息结束.

Let's say N=4 on number of B,C,D,E chains that A has. Ideally, each node E ends up with information like i=0, 1, 2, 3.

最重要的是,我可能想对B,C,D进行重新排序,因为它们非常类似于过滤器,因此我让它们都实现了

On top of this, I may want to re-order B, C, D as they are pretty much like filters so I have them all implementing an interface with

Response service(Request r);

我迫切希望远离辅助注入,因为新来的开发人员总是对此感到困惑(至少我一次又一次地注意到这一点,并且厌倦了这种教导,我也认为这有点丑陋和令人困惑).他们似乎不需要其他所有方面的培训就可以轻松上手.

I would like desperately to stay away from assisted inject as incoming developers always get confused by that (at least I have noticed this time and time again and am tired of teaching that and I too think it's a bit ugly and confusing). They seem to need no training on all the other stuff making it easy.

我在想,也许我只是注入一个提供者,B拥有一个C,C拥有一个D,然后它们都具有启动方法,但由于启动方法必须改变,这种情况并未如我所愿每个服务及其所有启动方法都必须匹配.可以看到,问题在于节点A拥有有关哪个节点号E的信息,并且需要将该信息传递给E,但是B,C和D不需要该信息.

I am thinking maybe I just inject a Provider and B has an C, C has a D and then they all have start methods but that sort of didn't pan out as I had hoped since the start method has to change on every service and all their start methods have to match. See, the issue is Node A has information on what node number E is and needs to get that information to E, but B, C, and D don't need that information.

我也许可以在A构造函数中进行一些接线并拥有

I could maybe do some wiring in the A constructor and have

Provider<B> bProvider
Provider<E> eProvider

但是,然后如何在整个链中获得E.我不太确定这样做的干净方法.

but then, how do I get E all the way down the chain. I am not quite sure of a clean way of doing this all.

谢谢, 院长

推荐答案

我可以想到三种方法来实现此目的:子注入器,手动DI和辅助注入.

I can think of three ways to do this: Child injectors, manual DI, and assisted injection.

这可能是最好的选择,两年前在我的回答中也列出了 .

This is probably the best option, also listed in my answer two years ago.

机器人腿问题" ,您可以创建一个子注入器,该子注入器允许您将@NodeNumber int绑定到树中的任何位置.这意味着即使过滤器顺序发生了变化,或者以后在C,D,F或它们的任何依赖关系中需要您的节点号,您的绑定和结构也不必更改很多.在您提供NodeNumber绑定之前,B,C,D,E不会被注入,但这对于您所描述的内容可能是正确的.

Taking a cue from the Guice documentation on the "robot legs problem", you could create a child injector that allows your @NodeNumber int binding anywhere in your tree that you'd like. This means your bindings and structure don't have to change much, even if the filter order changes, or if your node number is later needed in C, D, F, or any dependency thereof. B, C, D, an E won't be injectable until you provide a NodeNumber binding, but that's probably correct for what you're describing.

自然,您可以使用@Named("nodeNumber")代替定义@NodeNumber 绑定注释,或者您可以将其重构为保存在其他位置的BFactory.

Naturally, you could use @Named("nodeNumber") instead of defining a @NodeNumber binding annotation, or you could refactor into a BFactory you save elsewhere.

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获得或失去任何收益,需要改变什么.

Manual DI

If you only have a few dependencies that change infrequently, you can create your own stack manually. This may not use Guice to its full potential, but it's perfectly clear what's going on here, and what needs to change if B/C/D/E gain or lose any deps.

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))));
  }
}

辅助注射

您说过您想避免这种情况,但出于完整性考虑,我在这里列出.

Assisted injection

You said you were trying to avoid this, but I'm listing it here for completeness.

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
  }
}

尽管在这里辅助注射可能不是正确的选择,但它的使用非常简单,并且可以带走很多样板(特别是如果E有很多其他副产物等).

Though assisted injection may not be the right choice here, its use is pretty straightforward and it can take away a lot of boilerplate (particularly if E has a lot of other deps, etc).

这篇关于如何连接像过滤器这样的guice中的N个节点链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆