Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
JJUG	
  ナイト・セミナー 『Java	
  EE	
  特集』	

CDIをはじめよう	
NTTコムウェア株式会社 上妻 宜人 (あげつま のりと)	
はてなブログ : n-agetsuma.hatenablog.com	

Copyr...
少し前の話になりますが…	

Java EE

6 からついにEJBを使わない	

(2009年リリース)	

DI/AOPコンテナ仕様が入りました
DI求めてSpringに行かれた方、帰ってきて!	

(Spring	
  Framework	
  2002~)	

ロッド・ジョンソン 氏 著	
  
邦訳 :	
  実践J2EEシステムデザイン
本日のテーマ	
  
Context	
  and	
  
Dependency	
  InjecOon
本日のコンテンツ	
• 

Dependency Injection - DI の復習	

• 

CDIの機能紹介	
• 

インジェクション と スコープ	

• 

EL式との連携	

• 

インターセプタ	

• 

CDIのコンフィ...
コンテキスト (スコープ)を持った	

Context	
  and	
  
Dependency	
  InjecOon	
依存性の注入
コンテキスト (スコープ)を持った	

Context	
  and	
  
Dependency	
  InjecOon	
依存性の注入
Web3層構造で振り返る	
  
Dependency	
  InjecOon	
  の復習	
  
Web3層構造とnewによる依存性の連続性	
DAO/Repository	
Service	
REST	
  
Endpoint	

new	

new	

さらなる	
  
依存先クラス	
  

依存先	
  
クラス	
  

DBMS...
Web3層構造とnewによる依存性の連続性	
DAO/Repository	
Service	
REST	
  
Endpoint	

new	

new	

さらなる	
  
依存先クラス	
  

依存先	
  
クラス	
  

DBMS...
テストしたいのはREST	
  Endpointだけの場合	
DAO/Repository	
Service	
REST	
  
Endpoint	

new	

テスト	
対象	

new	

依存先	
  
クラス	
  

DBMS	

...
依存性の連続で結局全部必要になる	
DAO/Repository	
Service	
REST	
  
Endpoint	

new	

テスト	
対象	
ClassA	
  

new	

new	

さらなる	
  
依存先クラス	
  
...
依存性でユニットテストしにくい	
時間を消費	

時間がないのでユニットテスト困難	
  
最終的に	

ユニットテストしない	
  
こうしてテストのない	
  
レガシーコードが生まれ続ける。	
  

参考	
  :	
  翔泳社 レガシーコード改善ガイド
まずはインタフェースに依存を切り替えて	
DAO/Repository	
Service	
インタフェース	
  

REST	
  
Endpoint	

new	

さらなる	
  
依存先クラス	
  

DBMS	

call	
実装ク...
ここでnewしてしまうと効果があまりない	
public class ServiceImpl implements Service {
DAO/Repository	
…
さらなる	
  
Service	
@Override public v...
誰かが実装クラスを探して、	
  
自動でnewしてほしい	
  

DIコンテナの出番	
  
DIコンテナが実装クラスをnewして注入	
DAO/Repository	
さらなる	
  
依存先クラス	
  

Service	
インタフェース	
  

REST	
  
Endpoint	

DBMS	

call	
実装クラス	
 ...
DIコンテナが実装クラスをnewして注入	
DAO/Repository	
Service	

さらなる	
  
DIコンテナが型が合う実装クラスを	
  
依存先クラス	
  

@Path (“/sample”) インタフェース	
   探...
テスト時はフェイクに差替て、依存を断ち切る	
DAO/Repository	
さらなる	
  
依存先クラス	
  

Service	
インタフェース	
  

REST	
  
Endpoint	

フェイク実装	
  

ClassA	
...
再掲 :	
  各クラスを new	
  で繋いだ場合	
DAO/Repository	
Service	
REST	
  
Endpoint	

new	

テスト	
対象	
ClassA	
  

new	

new	

さらなる	
  
...
結果UTもしやすく、クラス間の依存も下がる	
DAO/Repository	
さらなる	
  
依存先クラス	
  

Service	
インタフェース	
  

REST	
  
Endpoint	

テスト	
対象	
ClassA	
  
...
DIの主なメリット	
各クラス間の依存性を弱めることができる	
•  特にユニットテストしにくい外部リソースへの依存に効果的	
  
•  データベースへのアクセス	
  
•  メールの送信	
  
•  他システムとの連携	
  

•  ...
CDIはここまで説明したDIコンテナの	
  
Java	
  EE	
  版 仕様です	
  
CDIについて
Context And Dependency Injection

(コンテキストと依存性の注入) 	
• 

Java EE 6 から CDI1.0 導入	

• 

Java EE 7 で CDI1.1 として小規模なアップデート	

• ...
Java	
  EE	
  仕様の中でのCDI位置づけ	
• 

DI機能によって各層間の依存性を解決する	

• 

EJB を使わないビジネスロジックの実現	
→ Java EE 5 まではEJBのみDIができた	
Client	

Jav...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
例 :	
  Servlet	
  に @Inject	
  する	
  
@WebServlet(“/sample”)	
  
public	
  class	
  SampleServlet	
  extends	
  HcpServlet...
例 :	
  RESTエンドポイントに @Inject	
  する	
  

@Path(“/sample”)	
  
public	
  class	
  SampleResource	
  	
  {	
  
	
  	
  	
  	
 ...
例 :	
  EJBも@Injectでインジェクション可能	
  

@Path(“/sample”)	
  
public	
  class	
  SampleResource	
  	
  {	
  
//	
  @EJB	
  
	
  ...
インジェクションされる側の条件	
  	
  
?	
  

<<interface>>	
  
Service	
  

call	

インジェクションされる側	
  
(@Injectを書く方)	

ServiceImpl	
  

条件 ...
CDIによって生成されたインスタンスには注入可能	

@Path(“/test”)
public class SampleResource {
@Inject
Service service;

public class ServiceImpl...
CDIによって生成されたインスタンスには注入可能	
CDIによって	
  
インスタンス生成	
@Path(“/test”)
public class SampleResource {
@Inject
Service service;

pub...
CDIによって生成されたインスタンスには注入可能	
CDIによって	
  
インスタンス生成	
@Path(“/test”)
public class SampleResource {
@Inject
Service service;

pub...
CDIに生成される側の条件	
  	
  
引数なしコンストラクタがあれば、どんなクラスも注入可能	

REST	
  Endpoint	
  等	
  

call	

<<interface>>	
  

Service	
  

Serv...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
インタフェースの実装が複数ある場合は?	
  
A.  インジェクションフィールドがnullのまま	
  
B.  デプロイに失敗する	
  
C.  最初にロードしたクラスをインジェクション	
インジェクション先コード	

@Inject	
...
インタフェースの実装が複数ある場合は?	
  
A.  インジェクションフィールドがnullのまま	
  
B.  デプロイに失敗する	
  
C.  最初にロードしたクラスをインジェクション	
インジェクション先コード	

@Inject	
...
静的な型解決	
  :	
  Qualifier	
  (修飾子) の使用	
1.	
  @Qualifier	
  が付与されたアノテーションを作成	

@Qualifier	
  
@RetenOon	
  (RunOme)	
  
@Targe...
静的な型解決	
  :	
  Qualifier	
  (修飾子) の使用	
2.	
  インジェクション先とBean両方に付与する	
OracleDAOをインジェクションしたい場合は@Injectと@Oracleを指定	

@Inject	
 ...
静的な型解決	
  :	
  Qualifier	
  (修飾子) の使用	
3.	
  インジェクション対象を変更したい場合	
PostgresDAOをインジェクションしたい場合は修飾子を書き換える。	

@Inject	
  
@Postgr...
実行時に実装型の解決をしたい場合	

で支払う	

ユーザA	

@Path(“/charge”)	
<<REST	
  Endpoint>>	
  

ChargeResource	
  

で支払う	

ユーザB	

<<interface...
動的な型解決	
  :	
  @Produces	
@Produces	
  メソッドと限定子を併用して動的な型の解決を行う	
@Path(“/charge”)	
  
@Credit	
<<REST	
  Endpoint>>	
  

Ch...
プロデューサのコード例	

@RequestScoped	
  
public	
  class	
  PaymentStrategy	
  {	
  

@Path(“/charge”)	

	
  	
  	
  	
  private	
...
プロデューサメソッドのコード例	

@RequestScoped	
  
public	
  class	
  PaymentStrategy	
  {	
  

@Path(“/charge”)	

	
  	
  	
  	
  priva...
プロデューサメソッドのコード例	

@RequestScoped	
  
public	
  class	
  PaymentStrategy	
  {	
  

@Path(“/charge”)	

	
  	
  	
  	
  priva...
プロデューサメソッドのコード例	

@RequestScoped	
  
public	
  class	
  PaymentStrategy	
  {	
  

@Path(“/charge”)	

	
  	
  	
  	
  priva...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
@RequestScoped	
  :	
  リクエスト受付~応答まで	
  

クライアント	

サーバ	

request	
response	

@RequestScoped	
  
public	
  class	
  SampleBe...
@SessionScoped	
  :	
  ログイン~ログアウト	
  

クライアント	

サーバ	
Login	

Logout	

@SessionScoped	
  
public	
  class	
  User	
  	
  
	...
@ConversaOonScoped	
  :	
  Session未満の任意長さ	
  

クライアント	

サーバ	
Login	
Begin	

End	
Logout	

@Named	
  
@ConversaOonScoped	
 ...
アプリケーションスコープの使い分け	
  
@Startupや@Lockが使いたい場合はEJBがお勧め。	
似たような機能が複数ある	
•  アプリケーションスコープ

@javax.enterprise.context.ApplicaOonS...
@Dependent	
  :	
  インジェクション先に合わせる (default)	
  
Servlet	
  

call	

サーブレットは	
  
シングルインスタンス	
  

<<interface>>	
  

Service...
CDIで使用可能なスコープ一覧	
  
スコープ	
•  リクエストスコープ

@javax.enterprise.context.RequestScoped	
  

•  会話スコープ

@javax.enterprise.context....
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
JSF	
  2.x	
  /	
  CDI	
  :	
  @NamedによるELバインディング	
  

<h:inputSecret value=“#{password.now} “ ..	

@Named	
  
@RequestSco...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
インターセプタとは	
  
メソッドの開始・終了に割込み,業務とは直接関連ないシステム処理を実行	
共通処理	

課金業務クラス	
  
注文受付クラス	
  
発送業務クラス	
  

Interceptor	

メソッド開始	

Inter...
インターセプタの作り方	
  
@InterceptorBindingを付与した自作アノテーションで実装と対象を関連付け	
1.	
  アノテーション作る	

2.	
  インターセプタ実装を作る	

@InterceptorBinding	
...
インターセプタの優先順位は?	
  
インターセプタの順序が重要な場合も多くある。	

セキュリティ処理	

3

2
ロギング処理	

1

開始	

トランザクション開始	

インターセプタ順序を定義したい	
業務処理	
課金業務クラス	
...
インターセプタとコンフィグ	
  
Java	
  EE	
  6	
  ではXMLが必須、 EE	
  7	
  では @Priority	
  が導入	
•  Java	
  EE	
  6	
  の場合 :	
  WEB-­‐INF/be...
CDIの代表的な機能	
  
•  実装インスタンスのインジェクション @Inject	
  
-  静的な型解決 @Qualifiler	
  
-  動的な型解決 @Produces	
  	
  
•  スコープ @RequestScope...
beans.xmlの配置	
  
Java	
  EE	
  6	
  ではbeans.xmlが必須、EE	
  7	
  からはオプション化	
•  Java	
  EE	
  6	
  の場合 :	
  WEB-­‐INF/beans.xm...
CDIを Java	
  EE	
  アプリでどう使うか
3層モデルの依存性をDIで繋ぐ	
技術の変化が激しい部分は、ロジックとは別層 (クラス)に切り出す	
Java EE の 3層アーキテクチャ	
Web 層	
REST	
  Endpoint	
  
(JAX-­‐RS2.x)	
  
Back...
3層モデルの依存性をDIで繋ぐ	
ビジネスロジックは特定技術に依存したくない	
Java EE の 3層アーキテクチャ	
Web 層	
REST	
  Endpoint	
  
(JAX-­‐RS2.x)	
  

ビジネス 層	

永続化層	...
3層モデルの依存性をDIで繋ぐ	
シンプルに new	
  で繋いでいくと …	
  	
  
Java EE の 3層アーキテクチャ	
Web 層	
REST	
  Endpoint	
  
(JAX-­‐RS2.x)	
  
Backing...
3層モデルの依存性をDIで繋ぐ	
冒頭の通り依存性が強くテストできない等 の課題	
Java EE の 3層アーキテクチャ	
Web 層	
REST	
  Endpoint	
  
(JAX-­‐RS2.x)	
  

永続化層	

ビジネス ...
3層モデルの依存性をDIで繋ぐ	
@Injectでユニットテストしやすく、依存性を少なく。	
Java EE の 3層アーキテクチャ	
Web 層	

クライアント	

REST	
  Endpoint	
  
(JAX-­‐RS2.x)	
 ...
EJBとの使い分け
@Transactional の導入 (Java EE 7)	
EJBの宣言的トランザクションがCDIでもできるようになった	

•  Spring	
  の@TransacOonalと同じように使える	
  
•  RunOmeExcepOo...
CDIとEJBの機能の比較	
CDI1.1	
ある	
  
(@Inject	
  等)	

ある	
  
(@Named)	

ある	
  
(@RequestScoped	
  等)	

ある	
  

EJB3.1	
ある	
  

DI...
Web構築にはCDIで十分、基幹機能はEJB継続使用	
CDI1.1	
ある	
  
(@Inject	
  等)	

ある	
  

(@Named)	
Web構築	
ある	
  
に使う	
)	
(@RequestScoped	
  等

...
CDIをより深く学ぶためには
CDIのマニュアル・ドキュメント 等	
•  Weldのドキュメント (CDI参照実装)	
  
•  hcp://docs.jboss.org/weld/reference/2.0.3.Final/en-­‐US/	
  

•  Java	...
hcps://glassfish.java.net/download.html	

GlassFish4	
  を今すぐダウンロードして是非試してみてください!	
  
ご清聴ありがとうございました。	
OracleとJavaは、Oracle	
...
Upcoming SlideShare
Loading in …5
×

JJUG 11月ナイトセミナー CDIをはじめよう

35,542 views

Published on

JJUG 11月ナイトセミナーの発表資料です。
DI使用時のインタフェース使用の要否については、はてなブログにて補足しています。
http://n-agetsuma.hatenablog.com/entry/2013/12/11/211017

Published in: Technology
  • Be the first to comment

JJUG 11月ナイトセミナー CDIをはじめよう

  1. 1. JJUG  ナイト・セミナー 『Java  EE  特集』 CDIをはじめよう NTTコムウェア株式会社 上妻 宜人 (あげつま のりと) はてなブログ : n-agetsuma.hatenablog.com Copyright  ©  NTT  COMWARE  2013
  2. 2. 少し前の話になりますが… Java EE 6 からついにEJBを使わない (2009年リリース) DI/AOPコンテナ仕様が入りました
  3. 3. DI求めてSpringに行かれた方、帰ってきて! (Spring  Framework  2002~) ロッド・ジョンソン 氏 著   邦訳 :  実践J2EEシステムデザイン
  4. 4. 本日のテーマ  
  5. 5. Context  and   Dependency  InjecOon
  6. 6. 本日のコンテンツ •  Dependency Injection - DI の復習 •  CDIの機能紹介 •  インジェクション と スコープ •  EL式との連携 •  インターセプタ •  CDIのコンフィグ beans.xml •  CDIの使いどころ/EJBとの機能比較 •  CDIをもっと学ぶためには – 参考文献
  7. 7. コンテキスト (スコープ)を持った Context  and   Dependency  InjecOon 依存性の注入
  8. 8. コンテキスト (スコープ)を持った Context  and   Dependency  InjecOon 依存性の注入
  9. 9. Web3層構造で振り返る   Dependency  InjecOon  の復習  
  10. 10. Web3層構造とnewによる依存性の連続性 DAO/Repository Service REST   Endpoint new new さらなる   依存先クラス   依存先   クラス   DBMS ClassA   JAX-­‐WS  Client new Service new 依存先   クラス   さらなる   依存先クラス   Mail  Client new 関連他システム さらなる   依存先クラス   メールサーバ
  11. 11. Web3層構造とnewによる依存性の連続性 DAO/Repository Service REST   Endpoint new new さらなる   依存先クラス   依存先   クラス   DBMS ClassA   JAX-­‐WS  Client new Service new 依存先   クラス   さらなる   依存先クラス   Mail  Client new 関連他システム さらなる   依存先クラス   メールサーバ
  12. 12. テストしたいのはREST  Endpointだけの場合 DAO/Repository Service REST   Endpoint new テスト 対象 new 依存先   クラス   DBMS ClassA   new さらなる   依存先クラス   JAX-­‐WS  Client Service new 依存先   クラス   さらなる   依存先クラス   Mail  Client new 関連他システム さらなる   依存先クラス   メールサーバ
  13. 13. 依存性の連続で結局全部必要になる DAO/Repository Service REST   Endpoint new テスト 対象 ClassA   new new さらなる   依存先クラス   依存先   クラス   DBMS ユニットテストに JAX-­‐WS  Client Service 依存先   クラス   必要なクラス new さらなる   依存先クラス   Mail  Client new 関連他システム さらなる   依存先クラス   メールサーバ
  14. 14. 依存性でユニットテストしにくい 時間を消費 時間がないのでユニットテスト困難   最終的に ユニットテストしない  
  15. 15. こうしてテストのない   レガシーコードが生まれ続ける。   参考  :  翔泳社 レガシーコード改善ガイド
  16. 16. まずはインタフェースに依存を切り替えて DAO/Repository Service インタフェース   REST   Endpoint new さらなる   依存先クラス   DBMS call 実装クラス   ClassA   JAX-­‐WS  Client call Service インタフェース   new さらなる   依存先クラス   Mail  Client 実装クラス   new 関連他システム さらなる   依存先クラス   メールサーバ
  17. 17. ここでnewしてしまうと効果があまりない public class ServiceImpl implements Service { DAO/Repository … さらなる   Service @Override public void doBusiness() 依存先クラス   { new インタフェース   dao.select(); REST   call } Endpoint 実装クラスでDBにアクセス 実装クラス   } DBMS ClassA   JAX-­‐WS  Client 自分でローカル変数にnewすると   @Path (“/sample”) Service ユニットテスト時にDBにアクセス   さらなる   call してしまう。 public class SampleResource { new 依存先クラス   インタフェース   public Entity sampleMethod () { Mail  Client さらなる   Service service =実装クラス   new 依存先クラス   new ServiceImpl(); service.doBusiness(); … 関連他システム メールサーバ
  18. 18. 誰かが実装クラスを探して、   自動でnewしてほしい   DIコンテナの出番  
  19. 19. DIコンテナが実装クラスをnewして注入 DAO/Repository さらなる   依存先クラス   Service インタフェース   REST   Endpoint DBMS call 実装クラス   ClassA   new JAX-­‐WS  Client call Service インタフェース   さらなる   依存先クラス   Mail  Client Inject 実装クラス   関連他システム さらなる   依存先クラス   new DIコンテナ  (Spring,  Seaser2,  Guice,  CDI)   メールサーバ
  20. 20. DIコンテナが実装クラスをnewして注入 DAO/Repository Service さらなる   DIコンテナが型が合う実装クラスを   依存先クラス   @Path (“/sample”) インタフェース   探してインスタンス注入する。 public class SampleResource { REST   DBMS call Endpoint 実装クラス   @Inject Service service; ClassA   new public Entity sampleMethod () { Service call インタフェース   service.doBusiness(); .. Inject 実装クラス   JAX-­‐WS  Client さらなる   依存先クラス   Mail  Client 関連他システム さらなる   依存先クラス   new DIコンテナ  (Spring,  Seaser2,  Guice,  CDI)   メールサーバ
  21. 21. テスト時はフェイクに差替て、依存を断ち切る DAO/Repository さらなる   依存先クラス   Service インタフェース   REST   Endpoint フェイク実装   ClassA   new JAX-­‐WS  Client call フィールド にセット DBMS call Service インタフェース   さらなる   依存先クラス   Mail  Client フェイク実装   new JUnitテストケース   関連他システム さらなる   依存先クラス   メールサーバ
  22. 22. 再掲 :  各クラスを new  で繋いだ場合 DAO/Repository Service REST   Endpoint new テスト 対象 ClassA   new new さらなる   依存先クラス   依存先   クラス   DBMS ユニットテストに JAX-­‐WS  Client Service 依存先   クラス   必要なクラス new さらなる   依存先クラス   Mail  Client new 関連他システム さらなる   依存先クラス   メールサーバ
  23. 23. 結果UTもしやすく、クラス間の依存も下がる DAO/Repository さらなる   依存先クラス   Service インタフェース   REST   Endpoint テスト 対象 ClassA   call フィールド にセット DBMS call フェイク実装   new ユニットテストに 必要なクラス Service インタフェース   JAX-­‐WS  Client さらなる   依存先クラス   Mail  Client フェイク実装   new JUnitテストケース   関連他システム さらなる   依存先クラス   メールサーバ
  24. 24. DIの主なメリット 各クラス間の依存性を弱めることができる •  特にユニットテストしにくい外部リソースへの依存に効果的   •  データベースへのアクセス   •  メールの送信   •  他システムとの連携   •  インタフェースの切り出しとDIをセットで使う   •  インタフェースに依存させて実装を差し替えやすくする   •  結果的に依存の連鎖を止めることができる  
  25. 25. CDIはここまで説明したDIコンテナの   Java  EE  版 仕様です  
  26. 26. CDIについて
  27. 27. Context And Dependency Injection
 (コンテキストと依存性の注入) •  Java EE 6 から CDI1.0 導入 •  Java EE 7 で CDI1.1 として小規模なアップデート •  DIを使って、クラス間を依存性を少なく連携させる為の仕様 CDIが使えるオープンソースAPサーバ GlassFish 4.0 CDI1.1 準拠 WildFly8 CDI1.1 準拠予定 JBoss AS 7 CDI1.0 準拠 Tomee 1.x CDI1.0 準拠
  28. 28. Java  EE  仕様の中でのCDI位置づけ •  DI機能によって各層間の依存性を解決する •  EJB を使わないビジネスロジックの実現 → Java EE 5 まではEJBのみDIができた Client Java EE 7 Specifications Web 層 JSF PCブラウザ ビジネス 層 EJB JAX-RS CDI WebSocket モバイル EIS 永続化層 EJBを使わない
 ビジネスロジックの実現 CDI (3層をDIコンテナで繋ぐ) JPA RDBMS 等
  29. 29. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  30. 30. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  31. 31. 例 :  Servlet  に @Inject  する   @WebServlet(“/sample”)   public  class  SampleServlet  extends  HcpServlet  {          @Inject          private  Service  service; APサーバが自動的にServiceインタフェースの   実装クラスを探してnewして注入
  32. 32. 例 :  RESTエンドポイントに @Inject  する   @Path(“/sample”)   public  class  SampleResource    {          @Inject          private  Service  service; APサーバが自動的にServiceインタフェースの   実装クラスを探してnewして注入
  33. 33. 例 :  EJBも@Injectでインジェクション可能   @Path(“/sample”)   public  class  SampleResource    {   //  @EJB          @Inject          private  SampleSessionBean  service; APサーバが自動的に   SessionBean実装を探して注入
  34. 34. インジェクションされる側の条件     ?   <<interface>>   Service   call インジェクションされる側   (@Injectを書く方) ServiceImpl   条件 :  コンテナ管理Bean  (newしてないインスタンス)  であること     •  Servlet  関連 @WebServlet      @WebFilter      @WebListener   •  EJB  Session  Bean   :  @Stateless  など   •  JAX-­‐RS  RESTエンドポイント :  @Path  など   •  CDIによって生成されたインスタンス  
  35. 35. CDIによって生成されたインスタンスには注入可能 @Path(“/test”) public class SampleResource { @Inject Service service; public class ServiceImpl implements Service { @Inject Repository repository; 実装クラスServiceImplの   インスタンスをインジェクション
  36. 36. CDIによって生成されたインスタンスには注入可能 CDIによって   インスタンス生成 @Path(“/test”) public class SampleResource { @Inject Service service; public class ServiceImpl implements Service { @Inject Repository repository;
  37. 37. CDIによって生成されたインスタンスには注入可能 CDIによって   インスタンス生成 @Path(“/test”) public class SampleResource { @Inject Service service; public class ServiceImpl implements Service { @Inject Repository repository; public class RepositoryImpl implements Repository {…} さらなるインジェクションが可能
  38. 38. CDIに生成される側の条件     引数なしコンストラクタがあれば、どんなクラスも注入可能 REST  Endpoint  等   call <<interface>>   Service   ServiceImpl   CDIに生成される側 •  引数なしコンストラクタを含むクラス   •  インタフェースの実装はなくても @Inject  でインジェクション可能   •  アノテーションもいらない完全なPOJO  (Plain  Old  Java  Object)  
  39. 39. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  40. 40. インタフェースの実装が複数ある場合は?   A.  インジェクションフィールドがnullのまま   B.  デプロイに失敗する   C.  最初にロードしたクラスをインジェクション インジェクション先コード @Inject   private  DAO  dao; 実装クラスが複数ある OracleDAO   <<interface>>   DAO   PostgresDAO  
  41. 41. インタフェースの実装が複数ある場合は?   A.  インジェクションフィールドがnullのまま   B.  デプロイに失敗する   C.  最初にロードしたクラスをインジェクション インジェクション先コード @Inject   private  DAO  dao; 実装クラスが複数ある OracleDAO   <<interface>>   DAO   PostgresDAO  
  42. 42. 静的な型解決  :  Qualifier  (修飾子) の使用 1.  @Qualifier  が付与されたアノテーションを作成 @Qualifier   @RetenOon  (RunOme)   @Target  ({METHOD,  FIELD,  PARAMETER,  TYPE})   public  @interface  Oracle  {}  
  43. 43. 静的な型解決  :  Qualifier  (修飾子) の使用 2.  インジェクション先とBean両方に付与する OracleDAOをインジェクションしたい場合は@Injectと@Oracleを指定 @Inject   @Oracle   private  DAO  dao; @Oracle   public  class  OracleDAO  … @PostgreSQL   public  class  PostgresDAO  …
  44. 44. 静的な型解決  :  Qualifier  (修飾子) の使用 3.  インジェクション対象を変更したい場合 PostgresDAOをインジェクションしたい場合は修飾子を書き換える。 @Inject   @PostgreSQL   private  DAO  dao; @Oracle   public  class  OracleDAO  … @PostgreSQL   public  class  PostgresDAO  …
  45. 45. 実行時に実装型の解決をしたい場合 で支払う ユーザA @Path(“/charge”) <<REST  Endpoint>>   ChargeResource   で支払う ユーザB <<interface>>   ChargeService   PaypalService   SquareService   ユーザに応じて実装を 変えたい
  46. 46. 動的な型解決  :  @Produces @Produces  メソッドと限定子を併用して動的な型の解決を行う @Path(“/charge”)   @Credit <<REST  Endpoint>>   ChargeResource   <<interface>>   ChargeService   return結果をInject @Credit  @Produces <<Producer>>   PaymentStrategy   インジェクションする型の   判断ロジックを実装 PaypalService   依存 SquareService   依存
  47. 47. プロデューサのコード例 @RequestScoped   public  class  PaymentStrategy  {   @Path(“/charge”)        private  PaymentType  paymentType;   <<REST  Endpoint>>   ChargeResource   @Path  (“/charge”)   public  class  ChargeResource  {          @Inject  @Credit            ChargeService  service;            … <<interface>>   ChargeService        @Credit  @Produces          public  ChargeService  getStrategy(PaypalService  paypal,  SqureService  square)  {   return結果をInject                switch  (paymentType)  {   PaypalService   SquareService                          case  P@Produces paypal;   ayPal  :  return   <<Producer>>                          case  Square  :  return  square;   PaymentStrateg 依存 依存                }   y          }          …
  48. 48. プロデューサメソッドのコード例 @RequestScoped   public  class  PaymentStrategy  {   @Path(“/charge”)        private  PaymentType  paymentType;   <<REST  Endpoint>>   ChargeResource   @Path  (“/charge”)   public  class  ChargeResource  {          @Inject  @Credit            ChargeService  service;            … <<interface>>   返り値型(ChargeService)と   ChargeService   限定子(@Credit)で括り付けられる。      @Credit  @Produces          public  ChargeService  getStrategy(PaypalService  paypal,  SqureService  square)  {   return結果をInject                switch  (paymentType)  {   PaypalService   SquareService                          case  P@Produces paypal;   ayPal  :  return   <<Producer>>                          case  Square  :  return  square;   PaymentStrateg 依存 依存                }   y          }          … 限定子を忘れると、型が不定となるデプロイエラーが発生するので注意
  49. 49. プロデューサメソッドのコード例 @RequestScoped   public  class  PaymentStrategy  {   @Path(“/charge”)        private  PaymentType  paymentType;   <<REST  Endpoint>>   ChargeResource   @Path  (“/charge”)   public  class  ChargeResource  {          @Inject  @Credit            ChargeService  service;            … <<interface>>   ChargeService        @Credit  @Produces          public  ChargeService  getStrategy(PaypalService  paypal,  SqureService  square)  {   return結果をInject                switch  (paymentType)  {   SquareService                          case  P@Produces paypal;   PaypalService   ayPal  :  return   <<Producer>>                          case  Square  :  return  square;   実装インスタンスはメソッド引数に   PaymentStrateg 依存 依存                }   y          }          … APサーバから渡される  
  50. 50. プロデューサメソッドのコード例 @RequestScoped   public  class  PaymentStrategy  {   @Path(“/charge”)        private  PaymentType  paymentType;   <<REST  Endpoint>>   ChargeResource   @Path  (“/charge”)   public  class  ChargeResource  {          @Inject  @Credit            ChargeService  service;            … <<interface>>   ChargeService        @Credit  @Produces          public  ChargeService  getStrategy(PaypalService  paypal,  SqureService  square)  {   return結果をInject                switch  (paymentType)  {   PaypalService   SquareService                          case  P@Produces paypal;   ayPal  :  return   <<Producer>>                          case  Square  :  return  square;   PaymentStrateg 依存 依存                }   インジェクションしたい実装を   y          }          … 条件に応じてreturnする。  
  51. 51. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  52. 52. @RequestScoped  :  リクエスト受付~応答まで   クライアント サーバ request response @RequestScoped   public  class  SampleBean  {  …  }     @Path  (“/sample”)   public  class  SampleResource  {          @Inject  SampleBean  bean;   リクエスト毎にインジェクションしなおす
  53. 53. @SessionScoped  :  ログイン~ログアウト   クライアント サーバ Login Logout @SessionScoped   public  class  User            implements  Serializable  {  …  }     @Model    //  JSF2.x   public  class  SampleController  {          @Inject  User  user;   同一セッション中は、状態が保持された   同じインスタンスがインジェクションされる  
  54. 54. @ConversaOonScoped  :  Session未満の任意長さ   クライアント サーバ Login Begin End Logout @Named   @ConversaOonScoped   public  class  ConversaOonController                      implements  Serializable  {            @Inject          private  ConversaOon  conversaOon;            public  void  begin()  {                  …                  conversaOon.begin();          }            public  void  end()  {                  …                  conversaOon.end();          }  
  55. 55. アプリケーションスコープの使い分け   @Startupや@Lockが使いたい場合はEJBがお勧め。 似たような機能が複数ある •  アプリケーションスコープ @javax.enterprise.context.ApplicaOonScoped   •  JSR-330のシングルトン @javax.inject.Singleton   •  EJBのシングルトン @javax.ejb.Singleton   @ApplicaOonScoped   (CDI) @Singleton   (JSR-­‐330) @Singleton   (EJB) 生存期間   初期化から~   アンデプロイまで 同じ 同じ デプロイ時初期化   ない   ない   @WebListnerと組合せが必要   左記に同じ   ある @Lock   ない   ない   ある シリアライズ対応   (クラスタ考慮?)   ある ない   仕様に言及なし   @Startup   ロック制御  
  56. 56. @Dependent  :  インジェクション先に合わせる (default)   Servlet   call サーブレットは   シングルインスタンス   <<interface>>   Service   ServiceImpl   @WebServlet(“/sample”)   public  class  SampleServlet  extends  HcpServlet  {   サーブレット生成時に          @Inject   一度だけインジェクション          private  Service  service;     //  デフォルトは @Dependent  であると暗黙的に判定   public  class  ServiceImpl  extends  Service  {…}
  57. 57. CDIで使用可能なスコープ一覧   スコープ •  リクエストスコープ @javax.enterprise.context.RequestScoped   •  会話スコープ @javax.enterprise.context.ConversaOonScoped   •  セッションスコープ @javax.enterprise.context.SessionScoped   •  アプリケーションスコープ 短い @javax.enterprise.context.ApplicaOonScoped   長い 擬似スコープ (pseudo  scope) •  依存先に応じる(デフォルト)      @javax.enterprise.context.Dependent   •  シングルトン  @javax.inject.Singleton  
  58. 58. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  59. 59. JSF  2.x  /  CDI  :  @NamedによるELバインディング   <h:inputSecret value=“#{password.now} “ .. @Named   @RequestScope   public  class  Password  {          private  String  now;          … @Named  @RequestScope   public  class  PassController  {          @Inject          private  Password  password;          …
  60. 60. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  61. 61. インターセプタとは   メソッドの開始・終了に割込み,業務とは直接関連ないシステム処理を実行 共通処理 課金業務クラス   注文受付クラス   発送業務クラス   Interceptor メソッド開始 Interceptor 共通処理 代表的なインターセプタ   •  ロギング   •  セキュリティ関連 (認証や認可処理)   •  トランザクションの開始、コミット、ロールバック制御   完了
  62. 62. インターセプタの作り方   @InterceptorBindingを付与した自作アノテーションで実装と対象を関連付け 1.  アノテーション作る 2.  インターセプタ実装を作る @InterceptorBinding   @Target  ({Method,  TYPE})   @RetenOon(RunOme)   public  @interface  Logging  {}   @Logging  @Interceptor   public  class  LoggingInterceptor  {      …      @AroundInvoke      public  void  log(InvocaOonContext  ic)  {              logger.debug(“log  message”);              return  ic.proceed();      } 3.  インターセプタ対象にバインドさせる @Logging   public  void  charge(int  amount)  {…}  
  63. 63. インターセプタの優先順位は?   インターセプタの順序が重要な場合も多くある。 セキュリティ処理 3 2 ロギング処理 1 開始 トランザクション開始 インターセプタ順序を定義したい 業務処理 課金業務クラス   注文受付クラス   発送業務クラス   終了
  64. 64. インターセプタとコンフィグ   Java  EE  6  ではXMLが必須、 EE  7  では @Priority  が導入 •  Java  EE  6  の場合 :  WEB-­‐INF/beans.xml  に設定 (1つしかなくても必須) <beans>   先に実行される        <interceptors>                  <class>interceptor.LoggingInterceptor</class>                  <class>intreceptor.SampleIntreceptor</class>          </interceptors>   後に実行される </beans> •  Java  EE  7  の場合 :  XMLなしで、@Priority  で代用が可能 先に実行される @Logging  @Interceptor   @Dependent   @Priority(ApplicaOon+10)   public  class  LoggingInterceptor  {   後に実行される @Sample  @Interceptor   @Dependent   @Priority(ApplicaOon+20)   public  class  SampleInterceptor  {  
  65. 65. CDIの代表的な機能   •  実装インスタンスのインジェクション @Inject   -  静的な型解決 @Qualifiler   -  動的な型解決 @Produces     •  スコープ @RequestScoped,  @SessionScoped  など   •  EL式との組み合わせ   •  インターセプタ @InterceptorBinding   •  コンフィグ beans.xml
  66. 66. beans.xmlの配置   Java  EE  6  ではbeans.xmlが必須、EE  7  からはオプション化 •  Java  EE  6  の場合 :  WEB-­‐INF/beans.xml  を含めるとCDIが有効化 インターセプタがない場合は、   中身は空ファイルで良い。 •  Java  EE  7  の場合 :  beans.xmlなしで有効化されるが、スコープ指定が必須 インジェクション先のスコープと同じにする場合でも、   省略せずに明示的に @Dependent  を付与する。 @Dependent public class ServiceImpl implements .. {
  67. 67. CDIを Java  EE  アプリでどう使うか
  68. 68. 3層モデルの依存性をDIで繋ぐ 技術の変化が激しい部分は、ロジックとは別層 (クラス)に切り出す Java EE の 3層アーキテクチャ Web 層 REST  Endpoint   (JAX-­‐RS2.x)   BackingBean   (JSF2.x)   ビジネス 層 永続化層 Service   (CDI  Bean)   Repository   (JPA2.x)   RDBMS クライアント WebSocket   Servlet   RDBMS以外の   永続化機構   (KVSなど)
  69. 69. 3層モデルの依存性をDIで繋ぐ ビジネスロジックは特定技術に依存したくない Java EE の 3層アーキテクチャ Web 層 REST  Endpoint   (JAX-­‐RS2.x)   ビジネス 層 永続化層 Service   (CDI  Bean)   Repository   (JPA2.x)   RDBMS BackingBean   (JSF2.x)   クライアント WebSocket   Servlet   業務例 :     ・ 電話設備の登録/削除を行う   ・ 支払いがなければ督促する   WebSocketが出ても、KVSが出ても   業務ロジックコードは変えたくない   RDBMS以外の   永続化機構   (KVSなど)
  70. 70. 3層モデルの依存性をDIで繋ぐ シンプルに new  で繋いでいくと …     Java EE の 3層アーキテクチャ Web 層 REST  Endpoint   (JAX-­‐RS2.x)   BackingBean   (JSF2.x)   永続化層 ビジネス 層 new new Service   (CDI  Bean)   new Repository   (JPA2.x)   RDBMS クライアント WebSocket   Servlet   RDBMS以外の   永続化機構   (KVSなど)
  71. 71. 3層モデルの依存性をDIで繋ぐ 冒頭の通り依存性が強くテストできない等 の課題 Java EE の 3層アーキテクチャ Web 層 REST  Endpoint   (JAX-­‐RS2.x)   永続化層 ビジネス 層 new new Service   (CDI  Bean)   new Repository   (JPA2.x)   RDBMS BackingBean   (JSF2.x)   クライアント テスト 対象 WebSocket   Servlet   テストに必要 RDBMS以外の   永続化機構   (KVSなど)
  72. 72. 3層モデルの依存性をDIで繋ぐ @Injectでユニットテストしやすく、依存性を少なく。 Java EE の 3層アーキテクチャ Web 層 クライアント REST  Endpoint   (JAX-­‐RS2.x)   ビジネス 層 永続化層 Service   (CDI  Bean)   Repository   (JPA2.x)   RDBMS REST処理 @Path(“/sample”)   public  class  Resource  {      @Inject      private  Service  service;   業務処理 DBアクセス public  class  Service  {   public  class  Repository  {      @Inject      private  Repository  …      @PersistenceContext      private  EnOtyManager  ..   インジェクション インジェクション
  73. 73. EJBとの使い分け
  74. 74. @Transactional の導入 (Java EE 7) EJBの宣言的トランザクションがCDIでもできるようになった •  Spring  の@TransacOonalと同じように使える   •  RunOmeExcepOonがthrowされたら自動的にロールバック public  class  BankService  {          …          //  口座振り替えメソッド          @TransacOonal(TransacOonal.TxType.REQUIRED)          public  void  transfer(int  amount)  {                  pay(amount);                    //  振り込み元から出金                  receipt(amount);        //  振込み先に入金          }
  75. 75. CDIとEJBの機能の比較 CDI1.1 ある   (@Inject  等) ある   (@Named) ある   (@RequestScoped  等) ある   EJB3.1 ある   DI/AOP   (@Inject,  @EJB  等) EL式連携   ない   スコープ   ない   (@Stateless  or  @Stateful)   (@TransacOonal) 宣言的   トランザクション   (@Stateless  or  @Stateful)   ない   非同期実行   ある   ない   MQ連携   ない   リモート実行   ない   タイマ機能   ある   (@Asynchronous)   ある   (@MDB)   ある   (@Remote)   ある   (@Schedule)  
  76. 76. Web構築にはCDIで十分、基幹機能はEJB継続使用 CDI1.1 ある   (@Inject  等) ある   (@Named) Web構築 ある   に使う ) (@RequestScoped  等 ある   EJB3.1 ある   DI/AOP   (@Inject,  @EJB  等) EL式連携   ない   スコープ   ない   (@Stateless  or  @Stateful)   (@TransacOonal) 宣言的   トランザクション   (@Stateless  or  @Stateful)   ない   非同期実行   ある   ない   MQ連携   ない   リモート実行   ない   タイマ機能   ある   (@Asynchronous)   ある   (@MDB)   基幹システムで 使う ある   (@Remote)   ある   (@Schedule)  
  77. 77. CDIをより深く学ぶためには
  78. 78. CDIのマニュアル・ドキュメント 等 •  Weldのドキュメント (CDI参照実装)   •  hcp://docs.jboss.org/weld/reference/2.0.3.Final/en-­‐US/   •  Java  EE  7  Turial  -­‐  PartⅤ  Context  and  Dependency  InjecOon  for  Java  EE   •  hcp://docs.oracle.com/javaee/7/tutorial/doc/partcdi.htm   •  CDI  1.1  仕様書   •  hcp://jcp.org/en/jsr/detail?id=346   •  書籍 :  O’Reilly  Java  EE  7  EssenOals   ©  O’Reilly  Media,  Inc.   •  hcp://shop.oreilly.com/product/0636920030614.do   •  書籍 :  Apress  Beginning  Java  EE  7   •  hcp://www.apress.com/9781430246268 ©  Apress  Media  LLC
  79. 79. hcps://glassfish.java.net/download.html GlassFish4  を今すぐダウンロードして是非試してみてください!   ご清聴ありがとうございました。 OracleとJavaは、Oracle  CorporaOon  及びその子会社、関連会社の米国及びその他の国における登録商標です。   文中の社名、商品名等は各社の商標または登録商標である場合があります。

×