13

一連の処理要素を実行し、Guice を介してそれらを結び付けたいと考えています。次のパスを想定しましょう。

  • interface Aによって実装され、class AImplいくつかの入力が必要です
  • interface Bclass BImpl必要に応じて実装A
  • interface Cclass CImpl必要に応じて実装B
  • interface Dclass DImpl必要に応じて実装C

A の依存関係は実行時にのみ解決でき、構成時には解決できません。この場合、通常のアプローチは、次のように、不足しているインスタンスをパラメーターとして受け取るファクトリを作成するためにアシスト インジェクションを使用することです。

public interface AFactory {
    public A createA(String input);
}

しかし、私が実際に欲しいのは次のようなものです:

public interface DFactory {
    public D createD(String inputForA);
}

AImpl階層全体に固有の依存関係を手動で渡したくありません。Guiceでこれを達成することは可能ですか? そうでない場合、インジェクションの利点を維持しながら、この問題をエレガントに回避する最良の方法は何ですか?

4

2 に答える 2

7

チート方法:input static 変数または singleton に固執しますThreadLocal。パイプラインが開始する前に設定し、終了後にクリアします。DI を介して他のすべてをバインドします。

ファンシーな方法:ではA、 a を参照し@PipelineInput String inputStringますが、メイン インジェクターにはバインドしないでください。@PipelineInputそれ以外の場合は、他のパイプライン関連クラスでの参照を含め、通常どおりに依存関係をバインドします。が必要な場合は、私が呼び出しているDの実装から取得してください。DFactoryPipelineRunner

public class PipelineRunner {
  @Inject Injector injector; // rarely a good idea, but necessary here

  public D createD(final String inputForA) {
    Module module = new AbstractModule() {
      @Override public void configure() {
        bindConstant(inputForA).annotatedWith(PipelineInput.class);
      }
    };
    return injector.createChildInjector(new PipelineModule(), module)
        .getInstance(D.class);
  }
}

当然のことながら、ABC、およびのバインディング試行は、 a がないためにD失敗します -- あなたが発見したように、それらの満たされていない依存関係でインジェクターを作成すると、 a が得られますが、これらのパイプラインベースの依存関係は簡単に分離できるはずです子インジェクターにインストールするモジュールに。PipelineRunner@PipelineInput StringCreationException

これがハックすぎると感じる場合は、PrivateModules も「親インジェクターを使用して実装されている」ことを思い出してください。また、依存性注入の全体的なポイントはinputForA、分離された方法でオブジェクト グラフ全体で利用できるような依存関係を作成することです。

于 2013-05-02T06:38:37.280 に答える
1

3 つのオプションが表示されます。inputそれらは、 forを変更する頻度によって異なりますA

input1)モジュール内で定数としてバインドします。これは、 を作成する前にその値を知っていて、Injector値を変更したくない場合にのみ機能します。見るbindConstant

A2)またはそのモジュール内の値をバインドするプライベート サブモジュールを使用inputします。基本的に、異なる値を持つ 2 つまたは 3 つのインスタンス グラフを使用できます。newPrivateBinderを参照してください。

3) Scopeala RequestScope, SessionScope, ... を使用します。この方法で入力を頻繁に変更できますが、定義するある時点でスコープに出入りする必要があります。例については、カスタム スコープを参照してください。

于 2013-05-01T13:00:29.103 に答える