kagamihogeの日記

kagamihogeの日記です。

The Java EE 7 TutorialのInjectionの章をテキトーに訳した

The Java EE 7 Tutorial4 Injectionの章をテキトーに訳した。

最近、以下のセクションを読んだわけだが、この章のDIの入門の入門的なことから書いてあるとこから読めば良かったかな~と少し思った。

4 Injection

この章ではJava EEのインジェクション(Injection)についての概要を述べ、プラットフォームが提供する二つのインジェクションの仕組みを説明します。二つの方法とは、リソースインジェクション(resource injection)とDI(dependency injection)です。

Java EEが提供するインジェクションの仕組みによって、自分で作成したオブジェクトでリソースへの参照を取得したり、直接インスタンス化することなく他オブジェクトの依存性を取得することが出来ます。インジェクションポイントとしてのフィールドにマーキングを行うアノテーションの一つを、フィールドやメソッドに付与することで、取得したいリソースとクラスから他への依存性を宣言します。そうすることで、実行時に要求されたインスタンスをコンテナが提供します。インジェクションはコードをシンプルにし、依存性の実装とコードとを分離します。

この章では以下のトピックを扱います。

  • Resource Injection
  • Dependency Injection
  • The Main Differences between Resource Injection and Dependency Injection

4.1 Resource Injection

リソースインジェクション(Resource injection)により、JNDI名前空間で利用可能なリソースをコンテナ管理オブジェクトへインジェクト可能になります。コンテナ管理オブジェクトは例えば、servlet, EJB, マネージドビーン(managed bean)などです。リソースインジェクションを使用して、データソース、コネクタ、JNDI名前空間で利用可能なカスタムリソースをインジェクションできます。

インジェクションされるインスタンス参照に使用する型は通常はインターフェースで、リソースの実装とコードとは切り離されています。

例として、以下のコードはGlassFish Serverに搭載されているJava DBへのコネクションを提供するデータソースオブジェクトをインジェクションします。

public class MyServlet extends HttpServlet {
    @Resource(name="java:comp/DefaultDataSource")
    private javax.sql.DataSource dsc;
    ...
}

フィールドベースのインジェクションに加えて、メソッドベースのインジェクションを使用してリソースをインジェクションすることも可能です。

public class MyServlet extends HttpServlet {
    private javax.sql.DataSource dsc;
    ...
    @Resource(name="java:comp/DefaultDataSource")
    public void setDsc(java.sql.DataSource ds) {
        dsc = ds;
    }
}

メソッドベースのインジェクションを使用するには、JavaBeansのプロパティ名規約に従うsetterメソッドを定義しなくてはなりません。規約とは、メソッド名をsetで始め、戻り値型はvoid、引数は一つのみ、のことです。

@Resourceアノテーションjavax.annotationパッケージに存在し、JSR 250 (Common Annotations for the Java Platform)で定義されています。リソースインジェクションは名前で解決(resolves by name)するため非タイプセーフです。リソースオブジェクトの型はコンパイル時には分からないので、オブジェクトと参照の型が不一致の場合にはランタイムエラーになります。

4.2 Dependency Injection

Dependency injectionは、通常のJavaクラスをマネージドオブジェクト(managed objects)に変換し、他のマネージドオブジェクトにそのクラスを注入します。DIを使用することで、任意のマネージドオブジェクトへの依存性を宣言可能になります。コンテナはインジェクションポイントへ依存性のインスタンスを実行時に自動的に提供し、また、インスタンスのライフサイクルを管理します。

Java EEのDIはスコープを定義しており、これはコンテナがインスタンス化したりインジェクションしたりするオブジェクトのライフサイクルを決定します。単一のクライアントリクエストにレスポンスすることだけが要求されるマネージドオブジェクト(通貨換算ツールなど)のスコープと、セッション内で複数のクライアントリクエストを処理することが要求されるマネージドオブジェクト(ショッピングカードなど)のスコープは、異なります。

マネージドオブジェクト(またはマネージドビーンmanaged beans)を定義し、それから、通常のクラスにスコープを割り当てることでインジェクション可能になります。

@javax.enterprise.context.RequestScoped
public class CurrencyConverter { ... }

マネージドビーンをインジェクトするにはjavax.inject.Injectアノテーションを使用します。

public class MyServlet extends HttpServlet {
    @Inject CurrencyConverter cc;
    ...
}

リソースインジェクションに対し、DIは型で解決(resolves by type)するのでタイプセーフです。マネージドビーンの実装とコードを分離するために、インターフェース型を使用してインスタンスをインジェクトし、インターフェースを実装するマネージドビーンを参照出来ます。

DIに関する詳細な情報については、Introduction to Contexts and Dependency Injection for Java EEの章をテキトーに訳した - kagamihogeの日記とJSR 299 (Contexts and Dependency Injection for the Java EE Platform)を参照してください。

4.3 The Main Differences between Resource Injection and Dependency Injection

表4-1は、リソースインジェクションとDIの主要な違いをまとめたものです。

表4-1 リソースインジェクションとDIの主要な違い

インジェクション方法 JNDIリソースを直接インジェクト可能 通常のJavaクラスを直接インジェクト可能 解決方法 タイプセーフ
リソースインジェクション Yes No リソース名 No
DI No Yes Yes

関連リンク