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