1

データ オブジェクトのグラフがあり、このグラフのノードごとに 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*/)
  }
}

ここでの意図は、グラフ上のすべてのノードに対して、 の新しいインスタンスと、 の依存関係の新しいインスタンスを作成することです。ServiceService

だから今、私はいくつかのオプションがあります:

  • guice支援された注入工場によって支えられています。これは私たちが現在行っていることであり、サービスが依存している場合は、ノードへの依存関係がすべてのサービスに依存している必要がありますnode。つまり、ここで補助注入ファクトリーを使用すると、service依存するクラスごとにそれを使用する必要があり、これは不快です。
  • ネストされたブートストラッパーと呼ばれるもの、つまり、新しいインジェクターを備えた新しいモジュール、事実上新しい環境を使用でき、その環境のセットアップでbind(Node.class).toInstance(node). このコードは最初の訪問時に実行され、その結果がキャッシュされます。
  • Guice のカスタム スコープを使用できます (と思います)。

私と私のチームがカスタム スコープを認識していなかったという理由だけで、いくつかの場所で 2 番目を実行しました。カスタム スコープの別の用途が 1 つありますが、それを実装するのは、私が望んでいたよりもはるかに複雑でした。このガイドに従うことは役に立ちますが、安全性の低い土地を掘り下げなければならないことは明らかであり、前回の訪問はそれほど楽しいものではありませんでした.

この動作を得るには、どの 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 に答える