今さら人には聞けない 入門 - seasar foundation · diコンテナを利用する方法...
TRANSCRIPT
© The Seasar Foundation and the others 2006. all rights reserved.1
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
今さら人には聞けない今さら人には聞けないAOPAOP入門入門
2006.11.12エスエムジー株式会社
小森 裕介([email protected])
© The Seasar Foundation and the others 2006. all rights reserved.2
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
はじめにはじめに
そんなことはない!・・・と思います
でも、AOPが開発の中で一般的になりつつあるのもまた事実・・・
そろそろ『知らない』って言えなくなってきたアナタに、AOPの基礎を50分で伝授します!
「えっ!?AOPって、もう『今さら聞けない』の?」
© The Seasar Foundation and the others 2006. all rights reserved.3
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
はじめまして!はじめまして!
•• 名前:名前:小森 裕介
•• BlogBlog::http://d.hatena.ne.jp/y-komori/•• 所属:所属:エスエムジー株式会社(http://www.smg.co.jp)
•• 主な仕事:主な仕事:– Javaによる集中監視制御システム設計・開発
– Webアプリケーションシステムの設計・開発
– 教育・各種執筆活動• 日経ソフトウェア「とことん作って覚える! Java入門」連載中
• 「なぜ、あなたはJavaでオブジェクト指向開発ができないのか」
•• Seasar2Seasar2とのかかわりとのかかわり– S2Containerコミッタ、S2JMSコミッタ、S2JFaceコミッタ
© The Seasar Foundation and the others 2006. all rights reserved.4
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
AOPAOPがなければ何が困る?がなければ何が困る?
• 具体例で考えてみよう!
– ジャンケンプログラムにロギング処理を追加したい!
© The Seasar Foundation and the others 2006. all rights reserved.5
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
Log4jLog4jでロギング処理を追加しよう!でロギング処理を追加しよう!
• ジャンケンの手を決めるメソッドへロギング処理を追加<<interface>>
Player
<<abstract>>
AbstractPlayer
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
コンピュータの手を決めるクラス
人間の入力した手を読み取るクラス
人間の入力した手を読み取るクラス
ロギング処理を追加ロギング処理を追加 ロギング処理を追加ロギング処理を追加
© The Seasar Foundation and the others 2006. all rights reserved.6
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
public class ComputerPlayer extends AbstractPlayer {private Tactics tactics;
private static final Logger logger = Logger.getLogger(ComputerPlayer.class);
public int showHand() {int hand = tactics.readTactics();logHand(hand);return hand;
}
public void setTactics(Tactics tactics) {this.tactics = tactics;
}
private void logHand(int hand) {switch (hand) {case Janken.STONE:logger.debug("コンピュータ:グー");break;
case Janken.SCISSORS:logger.debug("コンピュータ:チョキ");break;
case Janken.PAPER:logger.debug("コンピュータ:パー");break;
}}
}
BeforeBefore AfterAfter
・・・追加されたロギング処理
追加されたロギング処理追加されたロギング処理
public class ComputerPlayer extends AbstractPlayer {private Tactics tactics;
public int showHand() {int hand = tactics.readTactics();return hand;
}
public void setTactics(Tactics tactics) {this.tactics = tactics;
}}
© The Seasar Foundation and the others 2006. all rights reserved.7
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
ロギング処理を共通化したい!ロギング処理を共通化したい!
• ロギング処理に重複部分があるのでなんとかしたい
共通処理を別クラスに分離
共通処理を別クラスに分離
HandLogger+logHand()
<<interface>>
Player
<<abstract>>
AbstractPlayer
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
public class ComputerPlayer extends AbstractPlayer {private Tactics tactics;
@Overridepublic int showHand() {
int hand = tactics.readTactics();HandLogger.logHand(PlayerType.COMPUTER, hand);return hand;
}}
ロギングモジュールのロギングモジュールの呼び出し部分は除去できない呼び出し部分は除去できない
© The Seasar Foundation and the others 2006. all rights reserved.8
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
呼び出し部分が残ると何が問題か呼び出し部分が残ると何が問題か
• ロギングモジュールの呼び出し部が依存部分として残ってしまうロギング処理を削除しようとすると呼び出し元にも影響が出る
HandLogger+logHand()
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
HandLogger+logHand()
単独での再利用が不可能!単独での再利用が不可能!
モジュール側の再利用は簡単・・・
モジュール側の再利用は簡単・・・
© The Seasar Foundation and the others 2006. all rights reserved.9
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
似たようなクラスを作成するときの問題似たようなクラスを作成するときの問題
• 共通モジュールの呼び出しは開発者に依存してしまう
HandLogger+logHand()
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
xxxxPlayer
+showHand()
新しいクラスを作るとき新しいクラスを作るとき開発者が呼び出しを忘れてしまう開発者が呼び出しを忘れてしまう
© The Seasar Foundation and the others 2006. all rights reserved.10
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
非機能要件はモジュール単独分離が難しい非機能要件はモジュール単独分離が難しい
• 非機能要件に関する処理は、全機能に影響するため、モジュールとして分離しにくい
ロギング処理も非機能要件の一つ非機能要件・・・システムの本来の機能とは関係ないが、信頼性や保守性、使いやすさを向上させるための要件
機能要件A機能要件A 機能要件B機能要件B 機能要件C機能要件C 機能要件D機能要件D
非機能要件
各機能に共通する処理をモジュール化する方法はないの?
© The Seasar Foundation and the others 2006. all rights reserved.11
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
アスペクト指向は関心事の分離からアスペクト指向は関心事の分離から
• システムを2種類の要件に分け、横断的関心事を分離するのがアスペクト指向の考え方
ビジネスAビジネスA ビジネスBビジネスB ビジネスCビジネスC ビジネスDビジネスD
セキュリティ(アクセス制御、情報隠蔽、承認、完全性・・・)
信頼性(バックアップ、分散、冗長性の確保・・・)
運用情報(監視、稼働状況、負荷管理、障害状況・・・)
マイグレーション(配備、設定、保守、開発計画・・・)
【出典】 『Seasar2で学ぶDIとAOP』(arton著、技術評論社)p20
横断的関心事(Cross cutting concern)
横断的関心事(Cross cutting concern)
中心的関心事(Core concern)
中心的関心事(Core concern)
© The Seasar Foundation and the others 2006. all rights reserved.12
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
ジョインポイントとアドバイスジョインポイントとアドバイス
• アスペクト指向では、機能の中にジョインポイントを定義し、アドバイスをウィービングする
ビジネスAビジネスAビジネスBビジネスB
ビジネスCビジネスCビジネスDビジネスD
ジョインポイント(Joinpoint)処理を追加する場所
ジョインポイント(Joinpoint)処理を追加する場所
アドバイス(Advice)追加される処理
アドバイス(Advice)追加される処理
セキュリティ(アクセス制御、情報隠蔽、承認、完全性・・・)セキュリティ(アクセス制御、情報隠蔽、承認、完全性・・・)
信頼性(バックアップ、分散、冗長性の確保・・・)信頼性(バックアップ、分散、冗長性の確保・・・)
運用情報(監視、稼働状況、負荷管理、障害状況・・・)運用情報(監視、稼働状況、負荷管理、障害状況・・・)
マイグレーション(配備、設定、保守、開発計画・・・)マイグレーション(配備、設定、保守、開発計画・・・)
ウィービング(Weaving)処理を追加すること
ウィービング(Weaving)処理を追加すること
© The Seasar Foundation and the others 2006. all rights reserved.13
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
どのようなジョインポイントがあるか?どのようなジョインポイントがあるか?
• ジョインポイント(Joinpoint)はアドバイスを挿入
可能なプログラム上の位置
① 呼び出されたメソッドの開始点
② 呼び出されたメソッドの終了点
③ メソッドの呼び出し地点
④ フィールドの参照、更新地点
⑤ クラスの生成地点
private int x;methodA () {
methodB();
x = x + 1;
methodC();
new XXX();
}
private int x;methodA () {
methodB();
x = x + 1;
methodC();
new XXX();
}
methodB () {
}
methodB () {
}
methodC () {}
methodC () {}
①
②
③
③
④
⑤
© The Seasar Foundation and the others 2006. all rights reserved.14
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
ジョインポイントとアドバイスを結びつけるジョインポイントとアドバイスを結びつけるポイントカットポイントカット
• どのジョインポイントにどのアドバイスを結びつけるかはポイントカット(Pointcut)で指定する
プログラム実行の流れ(スレッド)
ポイントカット
アドバイスどのジョインポイントをどのアドバイスに結びつけるかを指定する
どのジョインポイントをどのアドバイスに結びつけるかを指定する
ジョインポイント
【出典】 『アスペクト入門』(千葉 滋 著、技術評論社)p47
© The Seasar Foundation and the others 2006. all rights reserved.15
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
実際にどうやって実現するの?実際にどうやって実現するの?
•AOP(Aspect-Oriented Programming:アスペクト指向プログラミング)
はどうやって実現するの?
1.専用コンパイラを利用する方法
AOPを利用するには2種類の方法がある
2.DIコンテナを利用する方法
© The Seasar Foundation and the others 2006. all rights reserved.16
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
専用コンパイラを利用する方法専用コンパイラを利用する方法
• AspectJによるAOPの実現
Javaソースコード
アスペクト(Aspect)
アドバイスとポイントカットを記述したもの
アドバイスとポイントカットを記述したもの
public aspect HandLogger {pointcut loggedMethods():
execution(void HumanPlayer.showHand())|| execution(void ComputerPlayer.showHand());
after():loggedMethods() {// ログ出力処理
}}
通常のJavaクラス通常のJavaクラス
AspectJコンパイラ
Javaクラスファイル
コンパイルと同時にウィービングを行って
クラスファイルを出力する
コンパイルと同時にウィービングを行って
クラスファイルを出力する
ポイントカットポイントカット
アドバイスアドバイス
© The Seasar Foundation and the others 2006. all rights reserved.17
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
DIDIコンテナを利用する方法コンテナを利用する方法
• DIコンテナ(Seasar2)によるAOPの実現
Javaソースコード
アドバイス(Javaソースコード)
Diconファイル
Javaコンパイラ
Javaコンパイラ
DIコンテナ(Seasar2)
実行時に内部でウィービングを行う
実行時に内部でウィービングを行う
アスペクトを記述アスペクトを記述
© The Seasar Foundation and the others 2006. all rights reserved.18
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
CoreConcernとCrossCuttingConcernを分離できた!
S2AOPS2AOPを体感してみよう!を体感してみよう!
• 「アスペクトでジャンケン」のロギング処理をS2AOPで書き直す
<<interface>>
Player
<<abstract>>
AbstractPlayer
ComputerPlayer
+showHand()
HumanPlayer
+showHand()
<<interface>>
MethodInterceptor
<<abstract>>
AbstractInterceptor
HandInterceptor
+invoke()
Seasar2に含まれるクラス
Diconファイル
アスペクトを記述
ロギングに関する記述はナシ!
© The Seasar Foundation and the others 2006. all rights reserved.19
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
S2AOPS2AOPでのでのDiconDiconファイルの記述ファイルの記述
• S2AOPではXML(Diconファイル)にアスペクトを記述する
<components><component name="player" class="org.seasar.jface.example.janken.impl.HumanPlayer"><aspect pointcut="showHand">handInterceptor</aspect>
</component>
<component name="computer" class="org.seasar.jface.example.janken.impl.ComputerPlayer"><aspect pointcut="showHand">handInterceptor</aspect>
</component>
<component name="handInterceptor" class="org.seasar.jface.example.janken.interceptors.HandInterceptor" /></components>
コンポーネントとして登録されたインターセプター(アドバイス)
コンポーネントとして登録されたインターセプター(アドバイス)
ウィービング対象のコンポーネント
ウィービング対象のコンポーネント
ウィービング対象のコンポーネント
ウィービング対象のコンポーネント
コンポーネントに対するアスペクト
コンポーネントに対するアスペクト
ポイントカットの指定(アドバイスを追加するメソッド)
ポイントカットの指定(アドバイスを追加するメソッド)
© The Seasar Foundation and the others 2006. all rights reserved.20
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
S2AOPS2AOPの仕組みの仕組み
• ちょっとだけS2AOPの仕組みを紹介しましょう・・・
HumanPlayer
+showHand()
HandInterceptor
+invoke()
public Object invoke(MethodInvocation invocation) throws Throwable {// 元のメソッド実行前に行いたい処理invocation.proceed();// 元のメソッド実行後に行いたい処理
}
HumanPlayer$S2AOP
+showHand()
オーバーライド
①
②
③
SeasarがJavassistを利用して
実行中にサブクラスを自動生成
SeasarがJavassistを利用して
実行中にサブクラスを自動生成
Javassist:国産のバイトコートエンジニアリングライブラリhttp://www.csg.is.titech.ac.jp/~chiba/javassist/
More Info!
© The Seasar Foundation and the others 2006. all rights reserved.21
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
Seasar2Seasar2の提供するインターセプターの提供するインターセプター
• TraceInterceptor– メソッド呼び出しのトレースを自動出力
• ThrowsInterceptor– 例外のキャッチを一括処理
• ToStringInterceptor– toString()メソッドを自動処理
• MockInterceptor– モックを使ったテストを支援
• DelegateInterceptor– メソッド呼び出しを別コンポーネントへ委譲
• SyncInterceptor– メソッド呼び出しを同期化
http://s2container.seasar.org/ja/aop.htmlMore Info!
© The Seasar Foundation and the others 2006. all rights reserved.22
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
S2DAOS2DAOととAOPAOP
• S2DAOもAOPによって実現されている– インターフェースしか用意していないのに処理が行われるのはどうして??
<<interface>>
xxxDao+insert()+update()+delete()
xxxDao$S2AOP+insert()+update()+delete()
DaoInterceptor
S2AOPで自動生成された
実装クラス
S2AOPで自動生成された
実装クラス
ユーザが作成したインターフェース
ユーザが作成したインターフェース
S2Daoの提供するインターセプタがDaoとしての
機能を提供
S2Daoの提供するインターセプタがDaoとしての
機能を提供
アスペクト指向でソースコード生成を伴わないスマートなDAOが可能に!
アスペクト指向でソースコード生成を伴わないスマートなDAOが可能に!
http://s2dao.seasar.org/ja/s2dao.htmlMore Info!
© The Seasar Foundation and the others 2006. all rights reserved.23
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
既存のクラスを拡張するインタータイプ宣言既存のクラスを拡張するインタータイプ宣言
• インタータイプ宣言とは– 既存のクラスの静的構造を変更するアスペクトの機能
• Seasar2.4で提供される新機能InterType– 既存のクラスに対してメソッドやフィールドを自由に追加可能
Point-x-y
+calcArea();
Point-x-y-color+calcArea();+setColor();
プログラム実行中に追加!
プログラム実行中に追加!
ソースコード自動生成に替わる手段として利用可能!ソースコード自動生成に替わる手段として利用可能!http://s2container.seasar.org/ja/aop.html#OriginalInterTypeMore Info!
© The Seasar Foundation and the others 2006. all rights reserved.24
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
アスペクト指向をさらに知りたい方へアスペクト指向をさらに知りたい方へ
• 『アスペクト指向入門』-Java・オブジェクト指向からAspectJプログラミングへ
– 著:千葉 滋– 価格:¥2,480+税
– 出版社:技術評論社– ISBN:4-7741-2581-4
© The Seasar Foundation and the others 2006. all rights reserved.25
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
ご質問についてご質問について
スピーカーブースでお待ちしています
気軽にお越しください
© The Seasar Foundation and the others 2006. all rights reserved.26
Seasar ConferenceSeasar Conference2006 Autumn2006 Autumn
ご静聴ありがとうございました