2

GWT-GINチュートリアルページの基本的なセットアップ手順に従いました。ステップ3(バインディングの宣言)を実行していて、GINのBinderAPIの使用方法を理解しようとしています。

public class MyModule extends AbstractGinModule {
    @Override
    public void configure() {
        // 1. Declare an instance of EventBus and make sure every
        // injection request pulls back the same instance.
        EventBus eventBus = new EventBus();
        bind(EventBus.class).to??? // no toInstance() method!

        // 2. Declare two instances of Fizz using different constructors,
        // and allow the injection of either of them.
        Fizz f1 = new Fizz(true, "oh yeah", null);
        Fizz f2 = new Fizz();
        bind(Fizz.class).to??? // no toInstance() AND don't know how to choose f1 or f2!

        // 3. Declare a List of Buzz objects and allow them to be
        // injectable.
        List<Buzz> buzzes = new ArrayList<Buzz>();
        configureBuzzes(buzzes); // adds configured Buzz objects to the list
        bind(???).to(buzzes); // no toInstance() methods AND how to bind List<?>.class?!

        // 4. Conditionally bind SomePlace to Place *only* when we want the default Place
        // that 'historyHandler.handleCurrentHistory()' will go to when called onModuleLoad.
        bind(Place.class).to(SomePlace.class); // forces me to only have SomePlace instances!
    }
}

上記の4つのユースケースは、私が苦労しているものです。それぞれ:

  1. EventBusクライアントが要求するたびに同じインスタンスを再利用するにはどうすればよいですか?
  2. 上記の#1から構築して、さまざまなシナリオで注入できる2つ以上のさまざまなインスタンスを作成するにはどうすればよいですか?
  3. List何かを注入する方法は?
  4. 上記の#2と同じかもしれませんが、2 + Placeサブクラスをバインドする方法はPlace.class

前もって感謝します!

4

1 に答える 1

7

Guice自体がどのように機能するか、およびGuiceとGinの違いを明らかにするのに役立つ良い質問。GinはGuiceとはまったく同じではありません。JavaScriptconfigure()を生成するときにメソッドが実行されるため、コンパイラは正しいタイプのセットでのみベイクします。そうしないと、アプリにJRE全体が含まれる可能性があります。これは、Ginがこれを行うのを少しだましているので、これを理解すると、GWTDIはもう少し意味があります。

基本的な考え方は、このconfigure()メソッドは配線のみを処理することを想定しており、インスタンスを作成することは想定されていないということです。これにより、1)に対する回答と、2)に対する回答の一部が提供されます。実際には、アプリの実行中に使用されるコード(Providerオブジェクト、@Providesメソッド、そしてもちろん、注釈が付けられたもの@Inject)を作成することは、逆である必要があります。つまり、JSにのみコンパイルされます。つまり、3)のようにメソッドを定義できますが、メソッドconfigureBuzzes内からこれらを呼び出す場合にのみ注意する必要があります。通常のアプリコードから呼び出すことは絶対にしないでください。configure()configure()

2)、3)、および4)の答えは、主にGuice自体が一般的にどのように機能するかに関係しています。私が提供する1)のソリューションは、通常のGuiceでも機能します。このアプローチを常に提案します。配線と実際のオブジェクトの構築を混合しないと、コードが読みやすくなる傾向があります。 。

  1. メソッドにインスタンスを作成するのではなくconfigure()、バインディングを作成するだけです。たとえば、バインディングを次のように設定できます。

    bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
    

    インスタンスを作成し、スコープをシングルトンにします。デフォルトでは、デフォルトのコンストラクターが使用されます。

    • デフォルト以外のコンストラクターを使用する場合は、いくつかのオプションがあります。特定のコンストラクターに@Inject。で注釈を付け、各値に注釈を付けることができます(これについては後で詳しく説明します)。または、プロバイダーまたは@Providesメソッドを作成してインスタンスを作成することもできます。繰り返しになりますが、これを意味のあるものにしたい場合があります@Singletonが、それはユースケースによって異なります(これはGinModuleの別のメソッドになります)。

      @Provides
      //@Singleton //optional, depends on your use case
      public Fizz provideFirstFizz() {
          return new Fizz(true, "oh yeah", null);
      }
      
    • 次に、2つの異なる種類の同じものをどのように提供しますか?Guiceでこれをどのように行いますか?Fizzそして、注入されたコードが正しいコードを取得することをどのように期待しますか?これらはおそらくすべて同じ答えを持っていることがわかります-必要なインスタンスを示す方法を見つける必要があります。それらはすべて同じタイプであるため、それだけでは十分ではありませんが、挿入されたフィールドの注釈など、他のヒントを提供できます。このようf1に必要なコードを言ってくださいf2

      @Inject
      @Red// Make up your own annotation, or use some existing ones
      private Fizz f1;
      
      @Inject @Blue private f2;
      

      これで違いを区別する方法があり、同じアノテーションを使用してそれらをバインドする必要があります。@Injectコンストラクターでnoを想定しているためFizz、呼び出しを行うことはできません。代わりに、providesメソッドbind()に追加します。@Blue

      @Provides
      @Blue
      //@Singleton //optional, depends on your use case
      public Fizz provideFirstFizz() {
          return new Fizz(true, "oh yeah", null);
      }
      

      これは「このメソッドProvides BlueFizzインスタンス」と読むことができます。の場合@Red、デフォルトのctorがあるため、次を使用できbind()ます。

      bind(Fizz.class).annotatedWith(Red.class);//... no need to specify type
                                                //in this case, but might want 
                                                //singleton
      

      詳細については、 https://code.google.com/p/google-guice/wiki/BindingAnnotationsを参照してください。

  2. 繰り返しますが@Provides、これに使用することも、型を作成してバインドすることもできますProvider<T>Provider<List<Buzz>>すでにいくつかのプロバイダーメソッドを実行しているので、 :を試してみましょう。

    public class BuzzListProvider implements Provider<List<Buzz>> {
        public List<Buzz> get() {
            List<Buzz> buzzes = new ArrayList<Buzz>();
            // Configure them... This might call on a @Inject defined
            // within this BuzzListProvider, on the ctor or a field, or
            // just some code in this method.
            return buzzes;
        }
    }
    

    次に、プロバイダーをそのリストにバインドします。

    // cant say List<Buzz>.class, use TypeLiteral instead
    bind(new TypeLiteral<List<Buzz>>(){})
        .toProvider(BuzzListProvider.class);
    //  .in(Singleton.class); if the list needs to be only created once
    
  3. あなたはあなたの要約に正確に正しいです-これは2とまったく同じです。私は通常、この種のケースに対処するために@DefaultPlace注釈を付けます(または単にそれを再利用できるように単純です)。@Default

于 2012-11-16T05:39:01.427 に答える