Locked History Actions

Diff for "guice/Manual/UserGuide/Scopes"

Differences between revisions 2 and 3
Deletions are marked like this. Additions are marked like this.
Line 78: Line 78:
||@Singleton|eager*||lazy|| ||@Singleton||eager*||lazy||
Line 85: Line 85:
If the object is stateful, the scoping should be obvious. Per-application is @Singleton, per-request is @RequestScoped, etc. If the object is stateless and inexpensive to create, scoping is unnecessary. Leave the binding unscoped and Guice will create new instances as they're required. オブジェクトがステートフルの場合、スコーピングをはっきりさせなければならない。
アプリに一つの場合は@Singleton、リクエストに一つの場合は@RequestScoped等など。
オブジェクトがステートレスで生成することが軽ければ、スコーピングは不要である。
バインディングをスコープ無しのままにしておけば、Guiceはそれが必要になった時にいつも新しいインスタンスを生成する。
Line 87: Line 90:
Singletons are popular in Java applications but they don't provide much value, especially when dependency injection is involved. Although singletons save object creation (and later garbage collection), getting a handle to the single instance requires synchronization. Singletons are most useful for: シングルトンはJavaアプリではポピュラーな存在だがあまり多くの価値をもたない、特に依存性注入される場合には。
シングルトンはオブジェクト生成を省略する(後のゴミ集めも省略する)が、唯一のインスタンスへのハンドルを取得するには同期が必要である。
シングルトンは以下のようなケースで有用である。
Line 89: Line 94:
    * stateful objects, such as configuration or counters
    * objects that are expensive to construct or lookup
    * objects that tie up resources, such as a database connection pool.
    * ステートフルなオブジェクト、コンフィギュレーションやカウンタなど
    * 生成したりルックアップしたりするのが高価な(時間やメモリが必要な)オブジェクト
    * データベースコネクションプールのようなリソースと結びついたオブジェクト
Line 95: Line 100:
Classes annotated @Singleton and @SessionScoped must be threadsafe. Everything that's injected into these classes must also be threadsafe.
Minimize mutability
to limit the amount of state that requires concurrency protection.
@Singleton、@SessionScoped等のアノテーションされたクラスはスレッドセーフである必要がある。
したがって、これらのに注入されるものもまたスレッドセーフである必要がある。
Line 99: Line 103:
@RequestScoped objects do not need to be threadsafe. It is usually an error for a @Singleton or @SessionScoped object to depend on an @RequestScoped one. Should you require an object in a narrower scope, inject a Provider of that object. 平行性からの保護の必要性のため、状態の量を制限するため[[guice/Manual/BestPractices/MinimizeMutability|変更可能性を最小限に]]する必要がある。

@RequestScopedオブジェクトはスレッドセーフである必要はない。
通常は、@Singleton,@SessionScopedが@RequestScopedに依存するのは間違いである。
より狭いスコープのオブジェクトに依存するようにすべきであり、そのオブジェクトのプロバイダを注入すべきである。

訳注:サーブレットでは一つのリクエスト・レスポンス間は一つのスレッドが用いられるため、@RequestScopedはシングルスレッドでの利用になる。

スコープ

デフォルトでは、Guiceは常に新しいインスタンスを作成して返す。 このふるいまいはスコープによって変更可能である。 スコープによってインスタンスを再利用することができる。 つまり、そのライフタイムをアプリケーション(@Singleton)、セッション(@SessionScoped)、リクエスト(@RequestScoped)と区別することができる。

Guiceはウェブアプリ用のスコープを定義するためのサーブレット拡張を提供している。 それ以外のアプリケーションでは、カスタムスコープを作成することができる。

スコープの適用

Guiceはスコープを識別するためにアノテーションを使う。 実装クラスにスコープアノテーションを適用することにより、そのタイプのスコープを指定することができる。 機能的にもそうだが、ドキュメント用ととしてもこれらのアノテーションは役に立つ。 例えば、@Singletonはこのクラスがスレッドセーフであるべきことを示す(訳注:そうとは限らないと思うけど)。

@Singleton
public class InMemoryTransactionLog implements TransactionLog {
  /* ここにあるものはすべてスレッドセーフであること */
}

スコープはbindにおいても指定することができる。

  bind(TransactionLog.class).to(InMemoryTransactionLog.class).in(Singleton.class);

また、@Providesメソッドに指定することもできる。

  @Provides @Singleton
  TransactionLog provideTransactionLog() {
    ...
  }

タイプ(のアノテーション)とbind()でスコープが異なる場合は、bind()の方が優先される。 アノテーションされたスコープをキャンセルしたい場合には、bind()時にScopes.NO_SCOPEを使うことができる。

リンクバインディングにおいては、スコープはバインディングソースの方に適用される。バインディングターゲットではない。 例えば、Bar,Grillインターフェースを実装するApplebeesというクラスがあるとする。 以下の二つのバインディングは二つのインスタンスを許す、一つはBar向けのもの、もう一つはGrill向けのものである。

  bind(Bar.class).to(Applebees.class).in(Singleton.class);
  bind(Grill.class).to(Applebees.class).in(Singleton.class);

なぜかというと、スコープはバインドされるタイプ(Bar, Grill)に適用されるからであり、それらのタイプを満足するバインディング(Applebees)ではないからである。 もしただ一つのインスタンスだけを作成したいのであれば、そのクラスに対して@Singletonアノテーションを使うか、あるいは別のバインディングを使う必要がある。

  bind(Applebees.class).in(Singleton.class);

このバインディングを使うと、他の二つのバインディングの.in(Singleton.class)句は不要になる。

in()句にはRequestScoped.classのようなアノテーションを入れることもできるし、ServletScopes.REQUESTといったインスタンスを入れることもできる。

  bind(UserPreferences.class)
      .toProvider(UserPreferencesProvider.class)
      .in(ServletScopes.REQUEST);

アノテーションを使った方が望ましい。そのモジュールは別のタイプのアプリケーションでも再利用可能だからだ。 例えば、@RequestScopedオブジェクトであれば、ウェブアプリにおけるHTTPリクエストのスコープとして使うこともできるし、 APIサーバのRPCリクエストとして使うことができるからだ。

Eagerシングルトン

Guiceは早期に生成されるシングルトンのための特別なシンタックスを持つ。

  bind(TransactionLog.class).to(InMemoryTransactionLog.class).asEagerSingleton();

Eagerシングルトンでは初期化エラーを早期に発見することができるし、エンドユーザは一貫性のあるきびきびした動きを得ることができる。 (これに対して)Lazyシングルトンでは、素早いedit-compile-run開発サイクルを提供する。 Stage enumにより、どちらのモードを選択するか決めることができる。

PRODUCTION

DEVELOPMENT

.asEagerSingleton()

eager

eager

.in(Singleton.class)

eager

lazy

.in(Scopes.SINGLETON)

eager

lazy

@Singleton

eager*

lazy

※Guiceはその知識のあるシングルトンについてのみ早期生成を行う。これらはモジュール内で指定されたものと、そこから依存されているものである。(訳注:@Singletonアノテーションはだめ?)

スコープの選択

オブジェクトがステートフルの場合、スコーピングをはっきりさせなければならない。 アプリに一つの場合は@Singleton、リクエストに一つの場合は@RequestScoped等など。 オブジェクトがステートレスで生成することが軽ければ、スコーピングは不要である。 バインディングをスコープ無しのままにしておけば、Guiceはそれが必要になった時にいつも新しいインスタンスを生成する。

シングルトンはJavaアプリではポピュラーな存在だがあまり多くの価値をもたない、特に依存性注入される場合には。 シングルトンはオブジェクト生成を省略する(後のゴミ集めも省略する)が、唯一のインスタンスへのハンドルを取得するには同期が必要である。 シングルトンは以下のようなケースで有用である。

  • ステートフルなオブジェクト、コンフィギュレーションやカウンタなど
  • 生成したりルックアップしたりするのが高価な(時間やメモリが必要な)オブジェクト
  • データベースコネクションプールのようなリソースと結びついたオブジェクト

スコープと平行性

@Singleton、@SessionScoped等のアノテーションされたクラスはスレッドセーフである必要がある。 したがって、これらのに注入されるものもまたスレッドセーフである必要がある。

平行性からの保護の必要性のため、状態の量を制限するため変更可能性を最小限にする必要がある。

@RequestScopedオブジェクトはスレッドセーフである必要はない。 通常は、@Singleton,@SessionScopedが@RequestScopedに依存するのは間違いである。 より狭いスコープのオブジェクトに依存するようにすべきであり、そのオブジェクトのプロバイダを注入すべきである。

訳注:サーブレットでは一つのリクエスト・レスポンス間は一つのスレッドが用いられるため、@RequestScopedはシングルスレッドでの利用になる。