Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JJUG Java仕様勉強会「CDI」

JJUG Java仕様勉強会「CDI」

2023/09/05に開催されたJJUG(日本Javaユーザーグループ)Java仕様勉強会「CDI: Contexts and Dependency Injection」の発表資料です。

https://jjug.doorkeeper.jp/events/162534

当日のプレイバックはこちらから
https://www.youtube.com/watch?v=7VV-zIsNA5I

Takakiyo Tanaka

September 05, 2023
Tweet

More Decks by Takakiyo Tanaka

Other Decks in Technology

Transcript

  1. 1
    JJUG(⽇本Javaユーザー会) Java仕様勉強会 2023年9⽉
    CDI: Contexts and
    Dependency Injection
    ⽇本IBM ⽥中 孝清 (Twitter @TTakakiyo)

    View full-size slide

  2. 2
    ⾃⼰紹介
    2
    n
    ⽥中 孝清
    n ⽇本アイ・ビー・エム株式会社
    オートメーションソフトウェア テクニカルセールス
    n WebSphere Application Serverなどの
    テクニカルセールスを20年以上担当
    n Twitter @TTakakiyo

    View full-size slide

  3. 3
    3
    CDIとは
    Contexts and Dependency Injection

    View full-size slide

  4. 4
    Contexts and Dependency Injectionとは
    n アノテーションで指定することによって,
    Beanの型に従ったタイプセーフな注⼊(インジェクション)を⾏うAPI
    4
    @Named
    @RequestScoped
    public class OrderOperation {
    ・・・・・・
    @Inject
    private BookShop shop;
    ・・・・・・
    }
    @Stateless
    public class BookShopBean extends Business
    implements ShopBook {
    ・・・・・・
    @Inject
    @ShopDb private DataSource shopDb;
    ・・・・・・
    }
    @Dependent
    public class Resources {
    @Produces
    @Resource(lookup="jdbc/ShopDB")
    @ShopDb public DataSource ds;
    }
    CDI管理Bean
    Session Bean
    • アノテーション「@Inject」でBookShop型のbeanを注⼊
    • CDI管理Beanとして実装されたものや
    JAX-WSのエンドポイントなどがCDI管理Beanとして利⽤可能
    • ServletなどのJava EEコンポーネントにも@Injectをサポート
    • アノテーション「@Inject」でデータソースを注⼊
    • 限定⼦(Qualifie)で⽬的のデータソースを指定
    • データソースを提供(@Produces)するクラス
    • 限定⼦(Qualifie)を付与

    View full-size slide

  5. 5
    n DI(Dependency injection, 依存性の注⼊)とは
    – コンポーネント間の依存関係をプログラムのソースコードから排除し,
    外部の設定ファイルなどで注⼊できるようにするソフトウェアパターンである
    – 依存関係がプログラムから外部に取り除かれることで,以下のようなメリットが発⽣する
    • 結合度の低下によるコンポーネント化の促進
    • 単体テストの効率化
    • 特定のフレームワークへの依存度低下
    – 出典: Wikipedia
    n 従来のJNDIによるlookupによるオブジェクトの取得や,Factoryクラス経由の取得に⽐べて,
    より簡潔に記述でき,柔軟に挙動を制御することができる
    n CDI は,DIの機能に加えて,
    コンポーネントであるbeanのライフサイクル・コンテキストの管理機能を提供
    – Contexts beanのライフサイクルをライフサイクル・コンテキストに関連付ける
    – Dependency Injection beanのインスタンスをインジェクション(注⼊)する
    5
    Contexts and Dependency Injectionの役割

    View full-size slide

  6. 6
    CDIの歴史(1)
    6
    CDI 1.0
    (JSR 299: Contexts and Dependency Injection for the Java EE platform)
    CDI 1.1/1.2
    (JSR 346: Contexts and Dependency Injection for the Java EE platform)
    CDI 2.0
    (JSR 365: Contexts and Dependency Injection for the Java EE platform)
    CDI 3.0
    (Jakarta Contexts and Dependency Injection)
    CDI 2.0
    (Jakarta Contexts and Dependency Injection)
    CDI 4.0
    (Jakarta Contexts and Dependency Injection)
    Java EE 8
    Java EE 7
    Java EE 6
    Jakarta EE 8
    Jakarta EE 9
    Jakarta EE 10

    View full-size slide

  7. 7
    CDIの歴史(2)
    7
    CDI 1.0
    (JSR 299: Contexts and Dependency Injection for the Java EE platform)
    CDI 1.1/1.2
    (JSR 346: Contexts and Dependency Injection for the Java EE platform)
    Java EE 7
    Java EE 6
    Java EEへの
    Dependency Injection機能の取り込み
    Bean Discovery Modeの改善や各種仕様の明確化など
    CDIの基本機能の完成

    View full-size slide

  8. 8
    CDIの歴史(3)
    CDI 2.0
    (JSR 365: Contexts and Dependency Injection for the Java EE platform)
    CDI 3.0
    (Jakarta Contexts and Dependency Injection)
    CDI 2.0
    (Jakarta Contexts and Dependency Injection)
    CDI 4.0
    (Jakarta Contexts and Dependency Injection)
    Java EE 8 Jakarta EE 8
    Jakarta EE 9
    Jakarta EE 10
    Java SE環境での使⽤にあわせて仕様を分割
    「Core CDI」「CDI in Java SE」「CDI in Java EE」
    javax名前空間からjakarta名前空間への移⾏
    Jakarta EE Core Profileの新設にあわせて
    CDI仕様とCDI lite仕様に分割

    View full-size slide

  9. 9
    CDIの実装
    n Weld(reference implementation)
    利⽤しているランタイム
    – Wildfly / JBoss EAP
    – Open Liberty / WebSphere Liberty
    – WebLogic
    – GlassFish
    – Payara
    n Apache OpenWebBeans
    利⽤しているランタイム
    – Apache TomEE
    9

    View full-size slide

  10. 10
    Injectionの仕組み
    n CDIでは多くの場合オブジェクトを直接代⼊するのではなく,
    Proxyを動的に⽣成して代⼊する
    – beanのメソッド呼出しはProxyによってdelegateされて実⾏される
    – これによりコンテクスチュアルな動作やライフサイクルの管理を実現している
    n この動的にProxyを作成する機能がGraalVMでは使⽤できないため,CDI liteが作成された
    – 動的機能を使わない範囲でCDIと同等の機能を可能な限り提供するのがCDI lite
    10
    Beanのインスタンス
    Beanのインスタンス
    Inject先の変数
    Inject先の変数
    Beanを継承したProxy
    ×直接代⼊するのではない
    Proxy経由で代⼊
    作成したManaged Bean

    View full-size slide

  11. 11
    11
    CDIによるInjection
    Dependency Injection

    View full-size slide

  12. 12
    CDIによる注⼊が⾏われるのは
    n CDI管理Beanのインスタンスをnewで⽣成しても,注⼊は⾏われない
    n CDIの注⼊は,以下のタイミングで⾏われる
    1. 指定されたJava EEのコンポーネントがロードされるとき
    2. 注⼊される管理BeanがCDIコンテナで⽣成されるとき
    3. CDI.current()で取得したCDIインスタンス経由で管理Beanのオブジェクトを取得した場合
    CDI cdi = CDI.current();
    MyService service = cdi.select(MyService.class).get();
    @Inject
    private HttpSession session;
    Servlet HttpSession
    @Inject
    private MyService service;
    Servlet
    @Inject
    private DataSource ds;
    管理Bean DataSouce
    @Inject
    private DataSource ds;
    管理Bean DataSouce

    View full-size slide

  13. 13
    CDIで注⼊が⾏われるJava EE/Jakarta EEのコンポーネント
    13
    仕様 コンポーネント
    Servlet
    • servlet
    • servlet filter
    • event listener
    • HTTP upgrade handler
    JSP
    • tag handler
    • tag library event listener
    JSF
    • managed class
    (詳細は JSF の仕様の "JSF Managed
    Classes and Java EE Annotations" を参
    照)
    JAX-WS
    • service endpoint
    • handler
    JAX-RS • JAX-RS component (CDI管理の場合)
    仕様 コンポーネント
    WebSocket • endpoint
    EJB • bean
    Interceptor • interceptor
    Java Persistence • entity listener
    Managed Beans • managed bean
    CDI
    • CDI-style managed bean
    • decorator
    Java EE Platform
    • main class (static)
    • login callback handler
    * 仕様名はJava EEのもの
    例︓
    JAX-RS(Java EE) → Jakarta RESTful Web Service(Jakarta EE)

    View full-size slide

  14. 14
    CDI管理Bean
    n CDI管理Bean (CDI-style Managed Bean) は,
    以下の全て条件を満たすJavaクラスである
    – コンクリートなJavaクラス(インターフェスや,abstractクラスでない)であるか
    または,@Decorator が付与されている
    – パラメーターなしのコンストラクターを持つ,または@Inject が付与されたコンストラクターを持つ
    – non-static なインナー・クラスでない
    – EJB として定義されていない
    – javax.enterprise.inject.spi.Extension を実装し ていない
    – @Vetoed が付与されていない,
    @Vetoed が付与されたパッケージ内に存在しない
    n CDI管理Beanは,特殊なJavaのクラスではない
    14

    View full-size slide

  15. 15
    beanの発⾒︓Bean Discovery Mode
    n CDIが,アーカイブ(JAR/WAR)からBeanを発⾒するためのモード
    – JARファイル︓ META-INF/beans.xmlで指定
    – WARファイル︓ WEB-INF/beans.xmlまたはWEB-INF/classes/META-INF/beans.xmlで指定
    n annotatedモード(デフォルト,推奨)
    – 以下の場合,annotatedモードでbeanの検索が⾏われる
    • アーカイブ内にbeans.xmlが存在しない
    • アーカイブ内にバージョン1.1以降のbeans.xmlが存在し,bean-discovery-modeがannotated
    – セッションBeanとBean定義アノテーションが付与されたCDI管理Beanがbeanとして認識される
    • Bean定義アノテーション:
    スコープを指定するアノテーション,@Dependent,@Interceptor,@Decorator,ステレオタイプのアノテーション
    n allモード
    – 以下の場合,allモードでbeanの検索が⾏われる
    • アーカイブ内に空のbeans.xmlが存在する
    • アーカイブ内にバージョン指定のないbeans.xmlファイルが存在する
    • アーカイブ内にバージョン1.1以降のbeans.xmlが存在し,bean-discovery-modeがall
    – セッションBeanと全てのCDI管理Beanがbeanとして認識される(意図しないクラスもbeanとして扱われる危険が)
    n noneモード
    – 以下の場合,noneモードになり,beanの検索は⾏われない
    • アーカイブ内にバージョン1.1以降のbeans.xmlが存在し,bean-discovery-modeがnone
    15
    基本的にこれで利用する

    View full-size slide

  16. 16
    注⼊は,まずBean Typeの⼀致によって⾏われる
    n CDI管理BeanのデフォルトのBean Type
    – ⾃⾝のタイプ
    – 親クラスのタイプ
    – 実装したインターフェースのタイプ
    – Object タイプ
    n セッションBeanのデフォルトのBean Type
    – 実装したインターフェースのタイプ
    – Object タイプ
    n @TypedアノテーションでBean Typeを限定できる
    – 例:@Typed({ BookShop.class, Business.class } )
    16
    @Dependent @Typed(BookShop.class)
    public class BookShopImpl extends Business
    implements BookShop {
    ・・・・・・
    }
    @Inject
    private BookShop shop;
    @Inject
    private Business business;
    型が合うので注⼊できる
    親クラスなのでデフォルトでは注⼊できるが
    @Typedで限定されているので注⼊できない
    ×

    View full-size slide

  17. 17
    限定⼦(Qualifier)
    n 注⼊候補が複数あるとき,
    限定⼦を付けることで対象を選ぶことができる
    17

    View full-size slide

  18. 18
    限定⼦(Qualifier)の定義⽅法(1)
    n 限定⼦は@Qualifierアノテーションを使⽤して定義する
    18
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import javax.inject.Qualifier;
    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    public @interface Synchronous {}
    限定⼦ Synchronous を定義している例
    • @Qualifier で,限定⼦であることを宣⾔
    • @Target で, METHOD, FIELD, PARAMETER および TYPE に付与できるアノテーションであることを宣⾔
    • @Retention(RUNTIME) で,実⾏時までアノテーション情報が残ることを宣⾔
    • @Inherited は指定していない(サブクラスには継承されないように宣⾔)
    限定⼦の定義例

    View full-size slide

  19. 19
    限定⼦(Qualifier)の定義⽅法(2)
    n メンバー(プロパティー)を持つ限定⼦も定義できる
    19
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import javax.inject.Qualifier;
    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    public @interface PayBy {
    PaymentMethod value();
    }
    メンバーを持つ限定⼦の定義例
    限定⼦ PayBy を定義している例
    • メンバー(プロパティー)にアクセスするための
    メソッド value() を追加
    • この例では,メンバーの型を enum を利⽤して定義
    • その他はメンバーを持たない限定⼦と同様
    public enum PaymentMethod {
    CASH, CREDIT_CARD, CHEQUE
    }
    @Dependent
    @Asynchronous
    @PayBy(PaymentMethod.CASH)
    class AsynchronousCachPaymentProcessor
    implements PaymentProcessor {
    ・・・・・・
    }
    限定⼦の使⽤例

    View full-size slide

  20. 20
    組み込みの限定⼦︓@Any, @Default, @New
    n @Any
    • javax.enterprise.inject パッケージ
    – 全ての bean に暗黙的に付与される限定⼦
    – @New 限定⼦が付与された場合のみ消える
    n @Default
    • javax.enterprise.inject パッケージ
    – 全ての bean に暗黙的に付与される限定⼦ (デフォルト限定⼦)
    – @Named以外の限定⼦が付与されると消える
    n @New
    • javax.enterprise.inject パッケージ
    – CDI 1.1 以降では⾮推奨(deprecated)
    – CDI 1.1 以降では @Dependent が付与されていると解釈される
    20
    @Dependent
    public class Order {
    ・・・・・・
    }
    @Dependent
    @Asynchronous
    public class AsynchronousPaymentProcessor
    implements PaymentProcessor {
    ・・・・・・
    }
    • @Anyと@Defaultの2つの限定⼦が
    付与されて いることになる
    • @Anyと@Asynchronousの2つの
    限定⼦が付与されていることになる
    • @Default は除去される

    View full-size slide

  21. 21
    組み込みの限定⼦︓ @Named
    n @Named
    • javax.inject パッケージ
    – bean 名を指定する限定⼦ (bean に名前を付ける限定⼦)
    • 例:@Named("userInfo")
    – bean 名は,JSF faceletsやJSPからbeanにアクセスするため
    に使⽤(EL から bean にアクセスするために使⽤)
    – ユーザー定義の限定⼦と違い,型チェックが⾏われないため
    タイプミスなどをコンパイル時に検出できないので注意
    (そのため,あまり利⽤は推奨されない)
    n デフォルトのbean名
    (@Named のみを指定した場合の bean 名)
    – CDI 管理 Bean 最初を⼩⽂字にしたクラス名
    – セッション Bean 最初を⼩⽂字にしたクラス名
    – プロデューサー・メソッド メソッド名
    (getter の場合はプロパティー名)
    – プロデューサー・フィールドフィールド名
    – 注⼊操作の場合 注⼊先のフィールド名,
    パラメーター名
    21

    View full-size slide

  22. 22
    22
    ライフサイクル
    Life cycle

    View full-size slide

  23. 23
    スコープ
    n beanのスコープを定義することで、
    beanをコンテキストに関連付け、bean のライフサイクルを管理できる
    – 必要な時に⾃動的にbeanを作成し、コンテキストが終了する時に⾃動的にbeanを破棄する
    – 同じコンテキスト内では、同じbeanが共有される / 異なるコンテキストでは異なるbeanが⽤意される
    – コンテクスチュアル(Contextual)な動作が実現できる
    n 以下の4つのスコープが定義されている
    • javax.enterprise.context パッケージ内のアノテーションで指定する
    – @Dependentは疑似スコープ(pseudo scope)で,コンテクスチュアルな動作にならない
    23
    アノテーション スコープ java.io.Serializable
    @RequestScoped 1回の HTTP リクエストの範囲
    @ConversationScoped 複数回の HTTP リクエストの範囲
    開発者が開始と終了を制御
    実装が必要
    @SessionScoped 1つの HTTP セッションの範囲 実装が必要
    @ApplicationScoped 1つのアプリケーションの範囲
    @Dependent 注⼊先ごとにインスタンスが作成され、
    注⼊先の変数と同じスコープを持つ

    View full-size slide

  24. 24
    コンテクスチュアルな動作
    n 例えば,HttpServletのインスタンス変数は,
    複数ユーザーの複数リクエスト間で共有されるが,
    この変数に注⼊された@SessionScopedのbeanは,CDIコンテナによって
    ユーザーのHTTPセッションごとに異なるインスタンスが作成されて,
    Proxyが正しいインスタンスにメソッド実⾏をdelegateする
    n また逆に,異なるクラスの異なる変数に注⼊が⾏われても,
    同⼀スコープであれば同⼀のインスタンスが利⽤される
    24
    public class PaymentServlet extends HttpServlet {
    @Inject
    ShoppingCart cart;
    ……
    }
    @SessionScoped
    public class ShoppingCart implements Serializable {
    ……
    }
    cart Proxy
    ShoppingCartの
    インスタンス
    ShoppingCartの
    インスタンス
    ShoppingCartの
    インスタンス

    View full-size slide

  25. 25
    スコープの制限
    n セッション Bean の場合は、使⽤できるスコープが限定される
    – StatefulセッションBean 任意のスコープ
    – StatelessセッションBean @Dependentのみ
    – SingletonセッションBean @ApplicationScopedまたは@Dependent
    n スコープを持つCDI管理Beanの実装では、コンテクスチュアルな動作を実現するための
    Client Proxyを⽣成するために以下の制約が追加される
    – パラメーターを持たない、private 以外のデフォルト・コンストラクターを持つ
    – クラスがfinalでない (サブクラスが作成できる)
    – public, protectedまたはdefault-accessの⾮staticなメソッドがfinalでない
    (メソッドがオーバーライドできる)
    – publicなフィールドが存在しない (フィールド値の変更はメソッド経由でのみ実⾏できる)
    25

    View full-size slide

  26. 26
    Conversationスコープの制御
    n Conversation (CDI コンテナーが提供する組み込み Bean の1つ)を注⼊
    • javax.enterprise.context パッケージ
    n Conversationのbegin()/end()メソッドを呼び出して、Conversationスコープを開始/停⽌
    26

    View full-size slide

  27. 27
    beanのインスタンス⽣成
    n CDI コンテナーは管理Beanのコンストラクターを
    呼び出して bean のインスタンスを作成する
    n 管理 Bean のコンストラクター
    – default-access, public, protected または private
    なコンストラクターが使⽤される
    – @Inject アノテーションが付与された
    コンストラクターが優先的に使⽤される
    – 存在しない場合は、デフォルト・コンストラクター
    (パラメーターなしのコンストラクター)が使⽤される
    n パラメーターの注⼊
    – パラメーターを持つ場合は
    CDIコンテナーが呼び出し時に注⼊する
    – パラメーターには限定⼦を付与できる
    27

    View full-size slide

  28. 28
    初期化メソッド (Initializer Methods)
    n CDI コンテナーはbeanのインスタンスを作成し、
    フィールドに注⼊を⾏った後に、
    初期化メソッドを呼び出す
    – 初期化メソッド内では、
    注⼊されたフィールドを使⽤できる
    n 初期化メソッド
    – @Inject を付与して定義
    – 複数個定義できる (定義しなくても良い)
    – default-access, public, protectedまたはprivateで、
    non-abstract, non-static, non-generic なメソッド
    – セッション Bean の場合は、interfaceに公開された
    ビジネス・メソッドである必要はない
    n パラメーターの注⼊
    – パラメーターを持つ場合は
    CDIコンテナーが呼び出し時に注⼊する
    – パラメーターには限定⼦を付与できる
    28

    View full-size slide

  29. 29
    コールバック・メソッド: PostConstruct
    n 「Dependency Injection for Java」で規定
    n @PostConstruct アノテーションを付与して定義
    • javax.annotation パッケージ
    n CDI コンテナーは bean の初期化メソッドの実⾏後に、
    PostConstructメソッドを呼び出す
    n PostConstructメソッド
    – default-access, public, protected または private で、
    non-abstract, non-static なメソッド
    – 「void <メソッド名>() 」の形式
    – @PostConstruct を付与できるメソッドは1つのみ
    n パラメーターの注⼊は⾏われない
    29

    View full-size slide

  30. 30
    コールバック・メソッド: PreDestroy
    n 「Dependency Injection for Java」で規定
    n @PreDestroyアノテーションを付与して定義
    • javax.annotation パッケージ
    n CDIコンテナーはbeanを破棄する直前に、
    PreDestroy メソッドを呼び出す
    n PreDestroy メソッド
    – default-access, public, protected または private で、
    non-abstract, non-static なメソッド
    – 「void <メソッド名>() 」の形式
    – @PreDestroy を付与できるメソッドは1つのみ
    n パラメーターの注⼊は⾏われない
    30

    View full-size slide

  31. 31
    31
    プロデューサーと
    ディスポーザー
    Producer / Disposer

    View full-size slide

  32. 32
    プロデューサーとディスポーザー
    n プロデューサー
    – コンストラクターで⽣成できないオブジェクトなどを
    CDIのbeanとして扱いたい時に使⽤する
    • オブジェクトはCDI管理Beanで無くても良い
    • オブジェクトの実装型が動的に変わっても良い
    • 特殊な初期化処理が必要なオブジェクトでも良い
    – beanのファクトリーとしての役割を持つ
    – Java EE のリソースやコンポーネントを
    @Inject で注⼊する場合にも使⽤する
    n ディスポーザー
    – プロデューサーが返したオブジェクトの
    クリーンナップ処理を⾏いたい時に使⽤する
    32
    @Inject
    private BookShop shop;
    @ ApplicationScoped
    public class BookShopImpl extends Business
    implements BookShop {
    ・・・・・・
    }
    CDIコンテナが
    インスタンスを⽣成して注⼊する
    public class BusinessFactory {
    @Produces @ApplicationScoped
    public BookShop createShopBook() {
    ・・・・・・
    }
    プロデューサーが提供する
    インスタンスを注⼊する

    View full-size slide

  33. 33
    プロデューサー・メソッド
    n 注⼊されるオブジェクトを返すメソッド
    n プロデューサー・メソッドの定義
    – @Producesアノテーションを付与
    • javax.enterprise.inject パッケージ
    – スコープを定義するアノテーションや,
    @Namedなどの限定⼦を付与可能
    – CDI管理BeanまたはセッションBeanのメソッド
    • default-access, public, protected または
    private で,static または non-static なメソッド
    – メソッドの戻り値の型で Bean Type が決まる
    n プロデューサー・メソッドのパラメーターの注⼊
    – パラメーターを持つ場合は
    CDIコンテナーが呼び出し時に注⼊する
    – パラメーターには限定⼦を付与できる
    33
    public class OrderFactory {
    @Produces @ConversationScoped
    public Order createCurrentOrder(
    Shop shop, @Selected Product product ) {
    Order order = new Order(product, shop);
    return order;
    }
    }
    • スコープが定義されたオブジェクトを返す例
    • パラメーターshopとproductが注⼊される
    • Bean TypeはOrderとなる

    View full-size slide

  34. 34
    注⼊ポイントのメタデータ (Injection Point Metadata)
    n CDIコンテナーは,beanが注⼊されたポイントのメタデーターを提供
    – メタデータの型はInjectionPoint
    • javax.enterprise.inject.spi パッケージ
    n プロデューサー・メソッドの引数に指定すると,
    CDIコンテナから提供される
    – 通常のCDI管理Beanでも,InjectionPoint型の変数に
    @Injectさせることで利⽤可能
    – ただし,注⼊先のBeanのスコープは@Dependentでないと
    いけない
    n ⽤途の例
    34
    @Produces
    Logger createLogger( InjectionPoint injectionPoint ) {
    return Logger.getLogger( injectionPoint.getMember().getDeclaringClass().getName() );
    }
    ログ出⼒⽤の bean を返す,プロデューサー・メソッドでの利⽤例
    public interface InjectionPoint {
    public Type getType();
    public Set getQualifiers();
    public Bean> getBean();
    public Member getMember();
    public Annotated getAnnotated();
    public boolean isDelegate();
    public boolean isTransient();
    }
    InjectionPoint の定義

    View full-size slide

  35. 35
    ディスポーザー・メソッド
    n プロデューサー・メソッドやフィールドが返した
    オブジェクトのクリーンナップ処理を実装できるメソッド
    n ディスポーザー・メソッドの定義
    – CDI管理BeanまたはセッションBeanのメソッド
    • default-access, public, protectedまたはprivateで,staticまたはnon-staticなメソッド
    – パラメーターにクリーンナップするオブジェクトを1つだけ指定する
    • プロデューサー・メソッドの戻り値の型やプロデューサー・フィールドの型に合致する必要がある
    • 限定⼦も加味される
    – パラメーターに @Disposes アノテーションを付与
    • javax.enterprise.inject パッケージ
    35
    public class UserDatabaseEntityManager {
    @Produces @ConversationScoped @UserDatabase
    public EntityManager create(EntityManagerFactory emf) {
    return emf.createEntityManager();
    }
    public void close(@Disposes @UserDatabase EntityManager em ) {
    em.close();
    }
    }
    • プロデューサー・メソッドと
    ディスポーザー・メソッドの例
    • 両者とも,EntityManager型の
    オブジェクトを処理する
    • 両者とも,ユーザー定義の限定⼦
    @UserDatabaseが付与されている

    View full-size slide

  36. 36
    プロデューサー・フィールド
    n 注⼊されるオブジェクトを⽰すフィールド
    – プロデューサー・メソッドの簡易版
    n プロデューサー・フィールドの定義
    – @Producesアノテーションを付与
    • javax.enterprise.inject パッケージ
    – スコープを定義するアノテーションや、
    @Named など の限定⼦を付与可能
    – CDI管理Beanまたは
    セッションBeanのフィールド
    • default-access, public, protected または
    private フィールド
    • セッション Bean の場合は、
    static なフィールドでなければならない
    – フィールドの型でBean Typeが決定
    36
    public class Shop {
    @Produces
    @ApplicationScoped
    @Catalog
    @Named("catalog")
    List products = ....;
    • スコープが定義された例
    • 限定⼦として、@Namedと
    ユーザー定義の@Catalogが付与されている
    • Bean TypeはListとなる

    View full-size slide

  37. 37
    Java EE リソースやコンポーネントの注⼊
    n Java EE リソースやコンポーネントを注⼊する場合
    – プロデューサー・フィールドに Java EE リソースやコンポーネントを注⼊するためのアノテーションを付与する
    – 同じ型のリソースなどは、限定⼦を付与して区別する
    37
    public class AppResources {
    @Produces @WebServiceRef( lookup="java:app/service/PaymentService" )
    PaymentWebService paymentWebService;
    @Produces @EJB( ejbLink="../their.jar#PaymentService" )
    PaymentEjbService paymentEjbService;
    @Produces @Resource( lookup="jdbc/CustomerDatasource" )
    @CustomerDatabase
    Datasource customerDatabase;
    @Produces @PersistenceContext( unitName="CustomerDatabase" )
    @CustomerDatabase
    EntityManager customerPersistenceContext;
    @Produces @PersistenceUnit( unitName="CustomerDatabase" )
    @CustomerDatabase
    EntityManagerFactory customerPersistenceUnit;
    }
    @Inject
    PaymentWebService paymentWeb;
    @Inject
    PaymentEjbService paymentEjb;
    @Inject
    @CustomerDatabase
    Datasource custDb;
    @Inject
    @CustomerDatabase
    EntityManager custEm;
    @Inject
    @CustomerDatabase
    EntityManagerFactory custEmf;

    View full-size slide

  38. 38
    38
    インターセプターと
    デコレーター
    Interceptor / Decorator

    View full-size slide

  39. 39
    インターセプター (Interceptor) と デコレーター(Decorator)
    n 両者とも処理を差し込むために使⽤できるが、
    ⽤途が異なる
    n インターセプター (Interceptor)
    – メソッド呼び出しやライフサイクル・イベントが
    発⽣した時に、クロスカティング(横断的)タスクを
    差し込むための機能
    – AOP (Aspect Oriented Programming)で使⽤し、
    ビジネス・ロジックの実装には使⽤しな い
    n デコレーター(Decorator)
    – メソッド呼び出しが発⽣した時に、
    ビジネス・ロジックを差し込んだり
    カスタマイズするための機能
    – ビジネス・ロジックの実装に使⽤する
    39

    View full-size slide

  40. 40
    インターセプター (Interceptor)
    n メソッド呼び出しやライフサイクル・イベントが発⽣した時に、
    クロスカティング(横断的)タスクを差し込むための機能
    – AOP (Aspect Oriented Programming) で使⽤し、ビジネス・ロジックの実装には使⽤しない
    – ログ出⼒、監査、プロファイリングなど、アプリケーション内で繰り返し現れる処理を実装するために使⽤する
    n ライフサイクルとコンテキスト
    – インターセプターは、関連付けられたオブジェクトと同じライフサイクルを持つ
    – メソッド呼び出しのインターセプターは、関連付けられたメソッドと同じコンテキストで呼び出される
    – ライフサイクル・イベントのインターセプターが呼び出されるコンテキストは規定されていない
    n インターセプターも CDI 管理 Bean なので、@Inject で他の bean を注⼊できる
    n 複数のインターセプターの優先度は@Priorityで指定する
    40

    View full-size slide

  41. 41
    インターセプターの利⽤
    n インターセプターを使⽤する場合は、以下の流れで 開発を⾏う
    1. インターセプター・バインディング・タイプを定義する
    • @InterceptorBindingを利⽤して独⾃アノテーションを定義
    2. インターセプターを実装する
    • @Interceptorアノテーションとバインディング・タイプを指定したクラスを実装
    3. インターセプターを対象に関連付ける
    • インターセプターの対象となるクラスやメソッドにバインディング・タイプを付与
    4. インターセプターを有効にする
    • beans.xmlファイルにインターセプターを登録する
    n 詳細な実装⽅法は割愛
    41

    View full-size slide

  42. 42
    デコレーター (Decorator)
    n メソッド呼び出しが発⽣した時に、
    ビジネス・ロジックを差し込んだりカスタマイズするための機能
    n デコレーターの実装
    – @Decorator アノテーションを付与
    – デコレートするbeanと同じBean Typeを持つ
    • デリゲーション・オブジェクトと同じ Bean Type を持つ
    – @Inject と @Delegate でデコレートする bean を注⼊
    • デリゲーション・オブジェクトを1つだけ注⼊
    • コンストラクターや初期化メソッドで注⼊することも可能
    – 全てのビジネス・ロジックを実装しなくても良い
    • abstract なクラスでも良い
    – デコレーターも CDI 管理 Bean なので、他の必要なbeanを注⼊できる
    n beans.xmlにデコレーターのクラスを登録
    42

    View full-size slide

  43. 43
    43
    その他の機能
    Others

    View full-size slide

  44. 44
    その他のCDIの機能(1)
    n bean の Programmatic Lookup
    – オブジェクトTを直接注⼊するのではなくInstanceを注⼊
    – 注⼊された側でInstanceから条件にあわせたオブジェクトを取得
    n 代替(Alternative)実装と特殊化(Specialization)
    – 通常は使⽤せず,テストでのみ使⽤するbeanを代替(Alternative)として定義できる
    – beans.xmlの記述で切り替えることが可能
    – 多くのクラスを⼀⻫に代替実装に切り替える⽅法として,特殊化(Specialization)が利⽤可能
    n イベント通知
    – bean間でイベントの送受信を⾏う
    – CDI が提供する Event>を注⼊して,それ経由でイベントの送信を⾏う
    – オブサーバーメソッドを定義してイベントの受信を⾏う
    n ステレオタイプ
    – 共通の役割を持つ(同じアノテーションを付与される)beanに対して,
    カプセル化された共通のアノテーションを提供する

    View full-size slide

  45. 45
    その他のCDIの機能(2)
    n 除外フィルター
    – 注⼊するbeanの対象から外すクラスを,beans.xmlに指定できる
    – 指定したクラスが存在する場合,しない場合や,指定したシステムプロパティの値などを条件に設定できる
    n CDI拡張
    – Beanの検索やライフサイクルの管理などを柔軟に拡張することができる
    – Extensionを実装しMETA-INF/services/javax.enterprise.inject.spi.Extensionに登録して利⽤する
    n プログラムによるインターセプターの制御
    – 通常はbeans.xmlで定義するインターセプターの制御を,アプリケーションからおこなうことができる
    45

    View full-size slide

  46. 46
    以下のURLからお申し込みください
    https://ibm.biz/ComMeetup2023

    View full-size slide