38

私は Guice を拡張AbstractModuleしており、拡張クラス内で Guice のインジェクターにアクセスする必要があります。もしそうなら、どのように可能ですか?

4

2 に答える 2

60

これは異常な要求です。モジュールは、ロジック ファイルというよりも構成ファイルに似ています。モジュールはインジェクターを作成するために読み取られ、インジェクターが作成されるとすぐに、モジュールはその仕事を完了します。単純なモジュールの場合、モジュールを破棄する準備が整うまで、インジェクターは文字通り存在しません。

いずれにせよ、クラス X を取得するために Injector を要求するのではなく、通常はProvider<X>. Guice は、 、、またはのバインディングに対してorを注入するXProvider<X>XProvider<X>@Provides Xので、ほとんどの場合、代わりにこれを行うことができます。そうは言っても、インジェクターを注入すると、インスタンスをリフレクティブに取得したり、インジェクターのバインディングを検査したりできます (など)。

モジュール内からインジェクターにアクセスする必要があるいくつかの正当な理由/設計を次に示します。

@Providesメソッドで:

モジュールには、 で注釈が付けられたメソッド@Providesにミニプロバイダーを含めることができます。Injectorこれは注入可能であることを忘れないでください: これらのメソッドのいずれかで Injector が必要な場合は、それをパラメーターとして受け入れることができます。

public class OneModule extends AbstractModule {
  @Override public void configure() { /* ... */ }

  @Provides YourDependency getYourDependency(Injector injector) {
    return injector.getInstance(Class.forName(yourDependencyName));
  }

  @Provides Something getSomething(SomethingImpl something) {
    return initialize(something); // preferred: only ask for what you need
  }

  @Provides SomethingElse getSomethingElse(Provider<Thing> thingProvider) {
    return new SomethingElse(thingProvider); // asking for a provider works too
  }
}

configure() でプロバイダーを取得するには:

AbstractModulesgetProvider()はまさにこの理由で公開されますがget()、インジェクターがプロバイダーを提供する準備が整う前 (構成時など) にそのプロバイダーを呼び出すと、エラーが発生します。

public class TwoModule extends AbstractModule {
  @Override public void configure() {
    bind(Thingy.class).toInstance(
        new MyThingy(8675309, getProvider(Another.class)));
  }
}

おそらく電話をかけることができますgetProvider(Injector.class)が、それが機能するかどうかはわかりませんし、なぜ電話したいのかもわかりません.

configure() でインスタンスを取得するには:

これは悪い考えです。すべての構成メソッドが実行されるまで、Guice はインスタンスを提供する準備ができていません。最も近い方法は、他のモジュールを使用して子インジェクターを作成し、それをこのモジュールに渡すことですが、それが必要になることはめったにありません。

public class MainClass {
  public static void main(String[] args) {
    Injector firstStage =
        Guice.createInjector(new OtherModule1(), new OtherModule2());
    // An alternative design would @Inject-annotate fields in ThreeModule
    // and get it from firstStage, but that's nonstandard and may be confusing.
    Injector secondStage =
        firstStage.createChildInjector(new ThreeModule(firstStage));
  }
}

public class ThreeModule extends AbstractModule {
  private final Injector otherInjector;

  public ThreeModule(Injector otherInjector) { 
    this.otherInjector = otherInjector;
  }

  @Override public void configure() {
    bindStuffBasedOn(otherInjector);
  }
}
于 2013-04-13T18:49:18.837 に答える
1

Injectorクラスまたはプロバイダーにを注入できますが、まばらに使用する必要があります

ここで見つけました:https://groups.google.com/d/msg/google-guice/EiMDuDGei1Q/glxFhHKHHjsJ

参照: https://github.com/google/guice/wiki/InjectingTheInjector

public class MyClass
{
    @Inject
    public MyClass(Injector injector) { ... }
}

public class MyModule extends AbstractModule {
    ...

    @Provides
    public Something provideSomething(Injector injector) { ... }

}
于 2020-07-09T10:04:34.953 に答える