ジョインポイント写像に基づく
ドメイン特化AO機構の開発手法
2010年7月22日 SIGSE 169
外村 慶二、鵜林 尚靖 (九大)
概要
•
アプリケーションに応じてAO機構のカスタマイズは有効
-
例:名前付きポイントカット
pointcut accountAdaption():
accCreate() ¦¦ accClose() ¦¦ balChange()
概要
•
アプリケーションに応じてAO機構のカスタマイズは有効
-
例:名前付きポイントカット
pointcut accountAdaption():
accCreate() ¦¦ accClose() ¦¦ balChange()
•
ドメイン特化の為にAO機構の拡張が必要な場合があり、
概要
•
アプリケーションに応じてAO機構のカスタマイズは有効
-
例:名前付きポイントカット
pointcut accountAdaption():
accCreate() ¦¦ accClose() ¦¦ balChange()
•
ドメイン特化の為にAO機構の拡張が必要な場合があり、
その方法は必ずしも明らかではない
-
イベントとジョインポイントの対応関係が複雑な時
概要
•
アプリケーションに応じてAO機構のカスタマイズは有効
-
例:名前付きポイントカット
pointcut accountAdaption():
accCreate() ¦¦ accClose() ¦¦ balChange()
•
ドメイン特化の為にAO機構の拡張が必要な場合があり、
その方法は必ずしも明らかではない
-
イベントとジョインポイントの対応関係が複雑な時
概要
•
アプリケーションに応じてAO機構のカスタマイズは有効
-
例:名前付きポイントカット
pointcut accountAdaption():
accCreate() ¦¦ accClose() ¦¦ balChange()
•
ドメイン特化の為にAO機構の拡張が必要な場合があり、
その方法は必ずしも明らかではない
-
イベントとジョインポイントの対応関係が複雑な時
-
アスペクトのインスタンス管理方法のカスタマイズが必要な時
•
PHPを対象として、Webアプリケーションのページアク
セスに着目したAO機構の拡張を事例に説明
2発表手順
•
問題意識
•
ドメイン特化の為のAO機構の拡張 (ケーススタディ)
-
ドメイン特化のジョインポイントの定義
-
ドメイン特化のAO機構の設計
-
ウィーバの拡張
•
関連研究
•
まとめと今後の予定
問題意識
Pointcut: 一分間以上滞在した ユーザのページアクセスに、 Advice: アンケートを表示する JavaScriptを追加 アンケート表示アスペクト
問題意識
例:アンケート表示アスペクト
•
Webアプリケーションの一連のページアクセスに横断的な関心事
•
ここではPHPをホスト言語とするAOPフレームワークのAOWPを使
Pointcut: 一分間以上滞在した ユーザのページアクセスに、 Advice: アンケートを表示する JavaScriptを追加 アンケート表示アスペクト
問題意識
例:アンケート表示アスペクト
•
Webアプリケーションの一連のページアクセスに横断的な関心事
•
ここではPHPをホスト言語とするAOPフレームワークのAOWPを使
用する
ページアクセスの取扱い
5Pointcut: 一分間以上滞在した ユーザのページアクセスに、 Advice: アンケートを表示する JavaScriptを追加 アンケート表示アスペクト
問題意識
例:アンケート表示アスペクト
•
Webアプリケーションの一連のページアクセスに横断的な関心事
•
ここではPHPをホスト言語とするAOPフレームワークのAOWPを使
ページアクセスの取扱い
ユーザごとの状態の取扱い
問題意識
ページアクセスに着目したAO機構
class
QuesAspect extends PerSessionAspect {
private
$_fstAccTime = time();
private
$_asked =
false
;
public function
__construct() {
$quesAdv =
new
AroundAdvice();
$allReqPC =
new
RequestPointcut('.*');
$chkTimePC =
new
IfPointcut('$aspect->isQuesTime()');
$quesAdv->setPointcut($allReqPC->opAnd($chkTimePC));
$quesAdv->setAdviceBody('ques');
$this
->addAdvice($quesAdv);
}
public function
ques(JoinPoint $jp) {
ob_start();
$jp->proceed();
$outputSource = ob_get_clean();
// アンケート表示のJavaScriptを出力に追加 (省略)
}
// 省略
}
6問題意識
ページアクセスに着目したAO機構
class
QuesAspect extends PerSessionAspect {
private
$_fstAccTime = time();
private
$_asked =
false
;
public function
__construct() {
$quesAdv =
new
AroundAdvice();
$allReqPC =
new
RequestPointcut('.*');
$chkTimePC =
new
IfPointcut('$aspect->isQuesTime()');
$quesAdv->setPointcut($allReqPC->opAnd($chkTimePC));
$quesAdv->setAdviceBody('ques');
$this
->addAdvice($quesAdv);
}
public function
ques(JoinPoint $jp) {
ob_start();
$jp->proceed();
$outputSource = ob_get_clean();
// アンケート表示のJavaScriptを出力に追加 (省略)
}
1分以上滞在したユーザのページアク セスを置き換えるアドバイス問題意識
ページアクセスに着目したAO機構
class
QuesAspect extends PerSessionAspect {
private
$_fstAccTime = time();
private
$_asked =
false
;
public function
__construct() {
$quesAdv =
new
AroundAdvice();
$allReqPC =
new
RequestPointcut('.*');
$chkTimePC =
new
IfPointcut('$aspect->isQuesTime()');
$quesAdv->setPointcut($allReqPC->opAnd($chkTimePC));
$quesAdv->setAdviceBody('ques');
$this
->addAdvice($quesAdv);
}
public function
ques(JoinPoint $jp) {
ob_start();
$jp->proceed();
$outputSource = ob_get_clean();
// アンケート表示のJavaScriptを出力に追加 (省略)
}
// 省略
}
1分以上滞在したユーザのページアク セスを置き換えるアドバイス 出力バッファリングを有効にして 元のページアクセスの処理を実行し アンケート表示のJavaScriptを追加 する 6問題意識
ページアクセスに着目したAO機構
class
QuesAspect extends PerSessionAspect {
private
$_fstAccTime = time();
private
$_asked =
false
;
public function
__construct() {
$quesAdv =
new
AroundAdvice();
$allReqPC =
new
RequestPointcut('.*');
$chkTimePC =
new
IfPointcut('$aspect->isQuesTime()');
$quesAdv->setPointcut($allReqPC->opAnd($chkTimePC));
$quesAdv->setAdviceBody('ques');
$this
->addAdvice($quesAdv);
}
public function
ques(JoinPoint $jp) {
ob_start();
$jp->proceed();
$outputSource = ob_get_clean();
// アンケート表示のJavaScriptを出力に追加 (省略)
}
1分以上滞在したユーザのページアク セスを置き換えるアドバイス 出力バッファリングを有効にして ユーザごとにアスペクトのインスタン スを関連付けて、ユーザの滞在時間を 管理問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
7問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
7問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
X
7問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
7問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
...$adv = new AfterAdvice();
$adv->setPointcut(requestPC(.*)); ...
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
afterアドバイス ...$adv = new AfterAdvice();
$adv->setPointcut(requestPC(.*)); ...
afterアドバイス
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
afterアドバイス ...$adv = new AfterAdvice();
$adv->setPointcut(requestPC(.*)); ...
afterアドバイス
問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
afterアドバイス ...$adv = new AfterAdvice();
$adv->setPointcut(requestPC(.*)); ...
afterアドバイス
afterアドバイス名前付きのポイントカット
ではうまく表現できない
7問題意識
AO機構の拡張の必要性
<?php
$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } ... ... // 省略 ... ... ?>
ページアクセスをPHPのスクリプトファイル実行と対応付ける
function requestPC($url) {
return new ScriptExecPointcut($url); }
名前付きポイントカット
// アドバイス定義
$adv = new AroundAdvice();
$adv->setPointcut(requestPC(.*)); ... // アドバイス本体の記述 $jp->proceed(); ... ... ...
aroundアドバイス
afterアドバイス ...$adv = new AfterAdvice();
$adv->setPointcut(requestPC(.*)); ...
afterアドバイス
afterアドバイス名前付きのポイントカット
ではうまく表現できない
ドメイン特化の為の
AO機構の拡張
Aspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
Aspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
Aspect ドメイン特化のAO機構 9Aspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
1. ドメイン特化のジョインポイントモデルの定義
Aspect ドメイン特化のAO機構Aspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
1. ドメイン特化のジョインポイントモデルの定義
2. ドメイン特化のAO機構の設計
Aspect ドメイン特化のAO機構 9Aspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
1. ドメイン特化のジョインポイントモデルの定義
Aspect ドメイン特化のAO機構 ポイントカット記述子の追加 アドバイスの織り込みの拡張 アスペクトインスタンスの管理機構の拡張 拡張したウィーバAspect 汎用的なAO機構 ホスト言語の プログラミングの実行モデル ホスト言語の言語機構 汎用的なAO機構のウィーバ
設計
実装
ドメイン特化AO機構の開発手順
1. ドメイン特化のジョインポイントモデルの定義
2. ドメイン特化のAO機構の設計
3. ウィーバの拡張
Aspect ドメイン特化のAO機構 ポイントカット記述子の追加 アドバイスの織り込みの拡張 アスペクトインスタンスの管理機構の拡張 拡張したウィーバ 9ドメイン特化のジョインポイントモデルの定義
ドメイン特化のイベントと
汎用的なジョインポイントの対応関係を定義
(
ジョインポイント写像
の定義)
in out in out スクリプト実行 ページアクセスを表すジョインポイント プログラム実行モデルに基づく ジョインポイント Mapping 1
ドメイン特化のジョインポイントモデルの定義
ドメイン特化のイベントと
汎用的なジョインポイントの対応関係を定義
(
ジョインポイント写像
の定義)
例:ページアクセスの場合 10in out in out スクリプト実行 ページアクセスを表すジョインポイント Mapping 1 in out in in out out exitもしくはdie 関数の呼び出し Mapping 2
ドメイン特化のジョインポイントモデルの定義
ドメイン特化のイベントと
汎用的なジョインポイントの対応関係を定義
(
ジョインポイント写像
の定義)
例:ページアクセスの場合in out in out スクリプト実行 ページアクセスを表すジョインポイント プログラム実行モデルに基づく ジョインポイント Mapping 1 in out in in out out exitもしくはdie 関数の呼び出し スクリプト実行 Mapping 2
ドメイン特化のジョインポイントモデルの定義
ドメイン特化のイベントと
汎用的なジョインポイントの対応関係を定義
(
ジョインポイント写像
の定義)
例:ページアクセスの場合ドメイン特化の処理単位に着目して
ジョインポイントのグループ
を定義
10ユーザ 1 ユーザ 2 Webサーバ全体の一連のページアクセス ユーザごとの一連のページアクセス in out in out スクリプト実行 ページアクセスを表すジョインポイント Mapping 1 in out in in out out exitもしくはdie 関数の呼び出し Mapping 2
ドメイン特化のジョインポイントモデルの定義
ドメイン特化のイベントと
汎用的なジョインポイントの対応関係を定義
(
ジョインポイント写像
の定義)
例:ページアクセスの場合ドメイン特化の処理単位に着目して
ジョインポイントのグループ
を定義
ドメイン特化のAO機構の設計
•
ドメイン特化のジョインポイントを直接選択する
ポイントカット記述子
の定義
•
ドメイン特化のジョインポイントモデルに基づく
アスペクトのインスタンス生成機構
の定義
例:ページアクセスの場合 11ドメイン特化のAO機構の設計
•
ドメイン特化のジョインポイントを直接選択する
ポイントカット記述子
の定義
•
ドメイン特化のジョインポイントモデルに基づく
アスペクトのインスタンス生成機構
の定義
例:ページアクセスの場合request
(url, forms, cookies, headers)
url : URLのパターン
forms : フォームデータの指定
cookies: クッキーデータの指定
headers: HTTPリクエストヘッダの指定
ページアクセスを選択する
ポイントカット記述子
ドメイン特化のAO機構の設計
•
ドメイン特化のジョインポイントを直接選択する
ポイントカット記述子
の定義
•
ドメイン特化のジョインポイントモデルに基づく
アスペクトのインスタンス生成機構
の定義
例:ページアクセスの場合request
(url, forms, cookies, headers)
url : URLのパターン
forms : フォームデータの指定
cookies: クッキーデータの指定
headers: HTTPリクエストヘッダの指定
ページアクセスを選択する
ポイントカット記述子
11ドメイン特化のAO機構の設計
•
ドメイン特化のジョインポイントを直接選択する
ポイントカット記述子
の定義
•
ドメイン特化のジョインポイントモデルに基づく
アスペクトのインスタンス生成機構
の定義
例:ページアクセスの場合request
(url, forms, cookies, headers)
url : URLのパターン
forms : フォームデータの指定
cookies: クッキーデータの指定
headers: HTTPリクエストヘッダの指定
ページアクセスを選択する
ポイントカット記述子
Webサーバ全体で1つ、各ユーザごとに
関連付けたアスペクトのインスタンス生成
Per Application Per Session Instance Instance Instance
ドメイン特化のAO機構の設計
•
ドメイン特化のジョインポイントを直接選択する
ポイントカット記述子
の定義
•
ドメイン特化のジョインポイントモデルに基づく
アスペクトのインスタンス生成機構
の定義
例:ページアクセスの場合request
(url, forms, cookies, headers)
url : URLのパターン
forms : フォームデータの指定
cookies: クッキーデータの指定
headers: HTTPリクエストヘッダの指定
ページアクセスを選択する
ポイントカット記述子
Webサーバ全体で1つ、各ユーザごとに
関連付けたアスペクトのインスタンス生成
11汎用的なAO機構の拡張
•
汎用的なAO機構のウィーバを拡張する
•
AOWPフレームワーク
-
アスペクト記述をPHPのクラスとして記述する
(AOPフレームワーク)
汎用的なAO機構の拡張
•
汎用的なAO機構のウィーバを拡張する
•
AOWPフレームワーク
-
アスペクト記述をPHPのクラスとして記述する
(AOPフレームワーク)
➡ ポイントカット記述子やアスペクトの種類の追加は
クラスの追加によって行う
(request, per-application, per-session)
汎用的なAO機構の拡張
•
汎用的なAO機構のウィーバを拡張する
•
AOWPフレームワーク
-
アスペクト記述をPHPのクラスとして記述する
(AOPフレームワーク)
➡ ポイントカット記述子やアスペクトの種類の追加は
クラスの追加によって行う
(request, per-application, per-session)
汎用的なAO機構の拡張
•
汎用的なAO機構のウィーバを拡張する
•
AOWPフレームワーク
-
アスペクト記述をPHPのクラスとして記述する
(AOPフレームワーク)
➡ ポイントカット記述子やアスペクトの種類の追加は
クラスの追加によって行う
(request, per-application, per-session)
-
ウィーバはPHPを用いたOOPによって実装
➡ 織り込み手順はウィーバのPHP記述を変更
Pointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)
AO機構の拡張
AO機構の為の構文の拡張
ポイントカット記述子は
Pointcut
クラスのサブクラスとして定義
_isJoinPointShadow:
引き数のジョインポイントがジョインポイント投影かを判定するメソッド
Pointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)
AO機構の拡張
AO機構の為の構文の拡張
ポイントカット記述子は
Pointcut
クラスのサブクラスとして定義
_isJoinPointShadow:
引き数のジョインポイントがジョインポイント投影かを判定するメソッド
_runtimeMatch:
実行時のジョインポイントの選択を記述するメソッド
13 RequestPointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)Pointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)
AO機構の拡張
AO機構の為の構文の拡張
ポイントカット記述子は
Pointcut
クラスのサブクラスとして定義
_isJoinPointShadow:
引き数のジョインポイントがジョインポイント投影かを判定するメソッド
アスペクトのインスタンス生成方法を指定する為の
記述子は
Aspect
クラスのサブクラスとして定義
RequestPointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)Pointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint) PerSessionAspect _sessionID _sessionTimeOut Aspect PerApplicationAspect Aspect
AO機構の拡張
AO機構の為の構文の拡張
ポイントカット記述子は
Pointcut
クラスのサブクラスとして定義
_isJoinPointShadow:
引き数のジョインポイントがジョインポイント投影かを判定するメソッド
_runtimeMatch:
実行時のジョインポイントの選択を記述するメソッド
アスペクトのインスタンス生成方法を指定する為の
記述子は
Aspect
クラスのサブクラスとして定義
13 RequestPointcut _isJoinPointShadow(JoinPoint) _runtimeMatch(JoinPoint)ベースプログラムを解析し 抽象構文木 (AST) を生成 ASTからジョインポイントを生成 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行う ASTからコードを生成する ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? 全てのアドバイスについて アスペクトのインスタンスを取得 アドバイスを実行 織り込み時 (コンパイル時) 実行時 全てのジョインポイントについて 全てのアドバイスについて 開始 停止 NO YES YES
AO機構の拡張
ウィーバの変更
NOベースプログラムを解析し 抽象構文木 (AST) を生成 ASTからジョインポイントを生成 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) 全てのジョインポイントについて ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行う ASTからコードを生成する ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? 全てのアドバイスについて アスペクトのインスタンスを取得 アドバイスを実行 織り込み時 (コンパイル時) 実行時 全てのジョインポイントについて 全てのアドバイスについて 開始 停止 NO YES YES
AO機構の拡張
ウィーバの変更
ドメイン特化の
ポイントカット記述子の為の拡張
NO 14ベースプログラムを解析し 抽象構文木 (AST) を生成 ASTからジョインポイントを生成 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行う ASTからコードを生成する ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? 全てのアドバイスについて アスペクトのインスタンスを取得 アドバイスを実行 織り込み時 (コンパイル時) 実行時 全てのジョインポイントについて 全てのアドバイスについて 開始 停止 NO YES YES
AO機構の拡張
ウィーバの変更
ドメイン特化の
ポイントカット記述子の為の拡張
NO ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行うベースプログラムを解析し 抽象構文木 (AST) を生成 ASTからジョインポイントを生成 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) 全てのジョインポイントについて ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行う ASTからコードを生成する ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? 全てのアドバイスについて アスペクトのインスタンスを取得 アドバイスを実行 織り込み時 (コンパイル時) 実行時 全てのジョインポイントについて 全てのアドバイスについて 開始 停止 NO YES YES
AO機構の拡張
ウィーバの変更
ドメイン特化の
ポイントカット記述子の為の拡張
ドメイン特化のアスペクトインスタンスの
生成機構の為の拡張
NO 14 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行うベースプログラムを解析し 抽象構文木 (AST) を生成 ASTからジョインポイントを生成 ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行う ASTからコードを生成する ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? 全てのアドバイスについて アスペクトのインスタンスを取得 アドバイスを実行 織り込み時 (コンパイル時) 実行時 全てのジョインポイントについて 全てのアドバイスについて 開始 停止 NO YES YES
AO機構の拡張
ウィーバの変更
アスペクトのインスタンスを取得ドメイン特化の
ポイントカット記述子の為の拡張
ドメイン特化のアスペクトインスタンスの
生成機構の為の拡張
NO ジョインポイントが ポイントカットに 適合するか? (ジョインポイント投影か?) ジョインポイントが ポイントカットで指定された 実行時の条件を満たすか? ジョインポイントと対応するASTに対して アドバイスを適用する為のAST変換を行うParser Pointcut Weaver weaveAllAspect() ASTManager parsePHPFile(fileName) generateWovenSource() isJoinPointShadow() Advice Aspect getAllAdviceArray() weaveAdvice(advice, joinPoint) WeaveCommand AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance) runtimeMatch(joinPoint, adviceIndex) Aspect executeAdvice(joinPoint, adviceIndex) 織り込み時 (コンパイル時) 実行時
AO機構の拡張
AOWPのウィーバの拡張
15Parser Pointcut Weaver ASTManager parsePHPFile(fileName) generateWovenSource() isJoinPointShadow() Advice Aspect getAllAdviceArray() WeaveCommand AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance) runtimeMatch(joinPoint, adviceIndex) Aspect executeAdvice(joinPoint, adviceIndex) 織り込み時 (コンパイル時) 実行時
AO機構の拡張
AOWPのウィーバの拡張
requestポイントカットのaround、afterの為に
AST変換の手順を変更
Parser Pointcut Weaver weaveAllAspect() ASTManager parsePHPFile(fileName) generateWovenSource() isJoinPointShadow() Advice Aspect getAllAdviceArray() weaveAdvice(advice, joinPoint) WeaveCommand AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance) runtimeMatch(joinPoint, adviceIndex) Aspect executeAdvice(joinPoint, adviceIndex) 織り込み時 (コンパイル時) 実行時 weaveAdvice(advice, joinPoint) WeaveCommand
AO機構の拡張
AOWPのウィーバの拡張
requestポイントカットのaround、afterの為に
AST変換の手順を変更
15Parser Pointcut Weaver ASTManager parsePHPFile(fileName) generateWovenSource() isJoinPointShadow() Advice Aspect getAllAdviceArray() WeaveCommand AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance) runtimeMatch(joinPoint, adviceIndex) Aspect executeAdvice(joinPoint, adviceIndex) 織り込み時 (コンパイル時) 実行時 WeaveCommand
AO機構の拡張
AOWPのウィーバの拡張
requestポイントカットのaround、afterの為に
AST変換の手順を変更
PerApplicationAspect
:
インスタンスをシリアライズして実現
PerSessionAspect
:
インスタンスをクッキーに保存したsessionIDを
関連付けてシリアライズして実現
Parser Pointcut Weaver weaveAllAspect() ASTManager parsePHPFile(fileName) generateWovenSource() isJoinPointShadow() Advice Aspect getAllAdviceArray() weaveAdvice(advice, joinPoint) WeaveCommand AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance) runtimeMatch(joinPoint, adviceIndex) Aspect executeAdvice(joinPoint, adviceIndex) 織り込み時 (コンパイル時) 実行時 weaveAdvice(advice, joinPoint) WeaveCommand
AO機構の拡張
AOWPのウィーバの拡張
AspectInstanceManager getInstance(aspectName) releaseInstance(aspectInstance)requestポイントカットのaround、afterの為に
AST変換の手順を変更
PerApplicationAspect
:
インスタンスをシリアライズして実現
PerSessionAspect
:
インスタンスをクッキーに保存したsessionIDを
関連付けてシリアライズして実現
15AO機構の拡張
requestポイントカットの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... $jp->proceed(); ... ...
•
aroundアドバイスのproceedの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit();
}
AO機構の拡張
requestポイントカットの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... $jp->proceed(); ... ...
•
aroundアドバイスのproceedの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... ProceedFlag::setIn(); try { $jp->proceed();
} catch (ProceedEndException $e) { } ... ...
アドバイスの本体の変換
•
afterアドバイスの為の拡張
16AO機構の拡張
requestポイントカットの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... $jp->proceed(); ... ...
•
aroundアドバイスのproceedの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // アドバイス本体の記述 ... ... ProceedFlag::setIn(); try { $jp->proceed();
} catch (ProceedEndException $e) { } ... ...
アドバイスの本体の変換
•
afterアドバイスの為の拡張
if (ProceedFlag::in()) {throw new ProceedEndException(); }
exit、die関数の前に例外を投げる処理を追加
(定義済みのアスペクトの追加)
AO機構の拡張
requestポイントカットの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... $jp->proceed(); ... ...
•
aroundアドバイスのproceedの為の拡張
<?php$name = $_POST[ name ];
$pass = $_POST[ password ]; if (!userCheck($name, $pass)) {
echo パスワードが異なります。 ; exit(); } // 省略 ?> // アドバイス本体の記述 ... ... ProceedFlag::setIn(); try { $jp->proceed();
} catch (ProceedEndException $e) { } ... ...
アドバイスの本体の変換
•
afterアドバイスの為の拡張
afterアドバイス afterアドバイススクリプト実行の最後とexit、die関数の前に
アドバイスの呼び出しを追加
if (ProceedFlag::in()) {throw new ProceedEndException(); }
exit、die関数の前に例外を投げる処理を追加
(定義済みのアスペクトの追加)
記述量の比較
class QuestionnaireAspect extends AOWP_PerSessionAspect { const INTERVAL = 10;
private $_firstAccessTime; private $_asked = false;
public function __construct() {
$this->_firstAccessTime = time();
$allReqPC = new AOWP_RequestPointcut('.*');
$quesAdv = new AOWP_AroundAdvice();
$chkTimePC = new AOWP_IfPointcut('$aspect->isQuesTime()');
$quesAdv->setPointcut($allReqPC->opAnd($chkTimePC)); $quesAdv->setAdviceBody('ques'); $this->addAdvice($quesAdv); } // 省略 }
class GPQuestionnaireAspect extends AOWP_Aspect { const INTERVAL = 10;
public function __construct() {
if (session_id() == null)
start_session();
if (!isset($_SESSION['asked']))
$_SESSION['asked'] = false;
if (!isset($_SESSION['asking']))
$_SESSION['asking'] = false;
if (!isset($_SESSION['visitTime']))
$_SESSION['visitTime'] = time();
$scrExePC = new AOWP_ScriptExecutionPointcut('.*');
$ifFstScrExePC = new AOWP_IfPointcut('isFstScrExe()');
$allReqPC = $scrExePC->opAnd($ifFstScrExePC);
$startBufAdv = new AOWP_BeforeAdvice();
$startBufAdv->setPointcut($allReqPC);
$startBufAdv->setAdviceBody('_startOutputBuf');
$this->addAdvice($startBufAdv);
$endBufAdv1 = new AOWP_AfterAdvice();
$endBufAdv1->setPointcut($allReqPC);
$endBufAdv1->setAdviceBody('_addQues');
$this->addAdvice($endBufAdv1);
$endBufAdv2 = new AOWP_BeforeAdvice();
$exitCallPC = new AOWP_FunctionCallPointcut('^exit|die$');
$endBufAdv2->setPointcut($exitCallPC);