1. ホーム
  2. java

[解決済み] Guice:Singleton.classと@Singletonの相違点

2022-02-08 07:52:28

質問

ガイスでは、何が違うのか。

// Inside your AbstractModule subclass:
@Override
public void configure() {
    bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
}

そして

@Override
public void configure() {
    bind(Service.class).to(ServiceImpl.class);
}

@Provides @Singleton
public ServiceImpl providesService() {
    return new ServiceImpl();
}

どちらも同じですか?どのような場合にどちらかを使うのでしょうか?よろしくお願いします。

解決方法は?

それらは ほぼ は同じです。その @Singleton 構文が便利です。 @Provides メソッド、またはクラスそのものにアノテーションを付けます (ただし、私はスコープアノテーションをモジュール内に保持する方が好きです)。

この違いは どのキーがSingletonとマークされているか とはあまり関係がない。 @SingletonSingleton.class (または Scopes.SINGLETON , asEagerSingleton , @Singleton クラスアノテーション、または toInstance 暗黙のシングルトン)であり、デフォルトの構文が何を容易にしているかということに関係しています。例えば

public class MyModule extends AbstractModule {
  @Override public void configure() {
    bind(A.class).to(AImpl.class).in(Singleton.class);

    bind(B.class).to(BImpl.class);
    bind(BImpl.class).in(Singleton.class);
  }

  @Provides @Singleton C provideC() { return new CImpl(); }

  @Provides @Singleton D provideD(DImpl dImpl) { return dImpl; }

  @Provides E provideE(EImpl eImpl) { return eImpl; }
  @Provides @Singleton EImpl provideEImpl() { return new EImpl(); }
}

上記では、インターフェイス A をクラス AImpl と、インターフェース B をクラス BImpl が、動作は異なります。

  • インジェクション A を取得すると、同じ AImpl のインスタンスを毎回作成します。
  • インジェクション AImpl を取得すると、別の AImpl とは毎回異なり、すべて A のインスタンスです。
  • インジェクション B を取得すると、同じ BImpl のインスタンスを毎回作成します。
  • インジェクション BImpl は、その同じ BImpl インスタンス B を注入します。

見ての通り、それぞれのキーは異なっており、GuiceはインターフェイスのみがSingletonでバインドされている場合、複数の実装インスタンスを許可します。もしあなたが AB しかし、同じInjectorから両方のインターフェースと実装をInjectした場合、異なる動作が見られるかもしれません。

同様のロジックは @Provides メソッドを使用します。

  • インジェクション C は常に同じ CImpl のインスタンスを作成します。
  • インジェクション CImpl は、新しい CImpl がない限り、毎回 CImpl に注入可能なパブリック ゼロ引数コンストラクタがない場合、注入は失敗します。
  • インジェクション D は常に同じ DImpl のインスタンスを作成します。
  • インジェクション DImpl は毎回新しいインスタンスを返しますが、 それぞれが D .
  • インジェクション E は、同じ EImpl のインスタンスを毎回作成します。
  • インジェクション EImpl は、その同じインスタンスを取得します。 E を注入します。

これにより、ある程度の柔軟性が確保されます。仮に Cache は、最近検索されたオブジェクトを一定数保持するものであり、ここで @User Cache@Product Cache は両方とも注射可能です。もし、あなたが bind(Cache.class).in(Singleton.class) の場合、オブジェクト間で共有されるCacheは1つになります。 Cache インジェクションを使用した場合)、一方 bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class) の場合、アノテーションされたキーはシングルトンスコープに保持され、各オブジェクトタイプは独自のキャッシュを持つことになります。