スライド 1

複数個のJoinpointの集合を
対象としたPointcutを
記述可能なアスペクト指向言語
理学部 情報科学科
指導教官 千葉 滋 助教授
学籍番号 01_14577 竹内 秀行
異なるクラス階層を持つ変更
 既存のソフトウェアに新しい役割を持たせる
 オブジェクト指向で設計すると階層構造が破綻
 別々に記述できたほうが開発しやすい
人材管理モジュール
給与台帳モジュール
社員
社員
平社員
調査担当
販売担当
管理職
調査担当部長
販売担当部長
調査部
調査担当
調査担当部長
販売部
販売担当
販売担当部長
クラスの合成
人材管理::販売担当
社員管理::販売担当
給与台帳::販売担当
名前()
部下()
表示()
表示()
表示()
部下()
給料()
表示()
名前()
給料()
名前()
 同じ対象を表現するクラス同士を合成する


それぞれのクラスが持つすべてのメソッドおよびフィールド
を一つのクラスから利用できるように
メソッド名が衝突した場合のルールは別に記述
既存のアスペクト指向言語
 AspectJ[Kiczalesら’01]


現在最も一般的なアスペクト指向言語
特徴点 (joinpoint) を探し出しコードを挿入


メソッド呼び出しやフィールドアクセス等
Pointcut

Joinpointを抽出するための記述
call(void System.out.println(..)) && within(Logger)

Advice

Joinpointの新しい振る舞いをJavaコードで定義
before() : log() { System.out.println(“[” + now() + “] ”); }
AspectJによるクラス階層の合成
 AspectJでの方針



クラス階層を別々に開発
インスタンス化時に関連付け
メソッド呼び出し等をpointcut
 AspectJの問題点

pointcut で単一の joinpoint しか抽出できない


リフレクションを利用しなければならない
一方向にしか関連付けることができない
単一のJoinpointの制限①
人材管理
給与台帳
調査担当 Aspect
販売担当 Aspect
販売担当
調査担当
インスタンス化時にClass.forName()で
探してバインド
 インスタンス化を pointcut し、リフレクションで関連付け
 実行速度の低下
単一のJoinpointの制限②
人材管理::販売担当
表示()
部下()
Aspect
名前()
給与台帳::販売担当
表示()
給料()
名前()
 一方向にしか関連付けることができない
 基となるモジュールをあらかじめ決める必要がある
 逆方向の参照はオブジェクト同士のマッピングが必要
提案:複数個のJoinpointの集合を
選択できるPointcutの記述
 pointcut に連結演算子(##)を導入
 pointcut式 ## pointcut式


左右の式で得られるjoinpoint集合の配列を連結
従来の pointcut式の結果 は要素1の配列として扱う
 利用例
 人材管理パッケージのクラスと給与台帳パッケー
ジのクラスを抽出
class(personnel.*) ## class(payroll.*)

Jugglingクラスのstart()とend()の呼び出しを抽出
call(Juggling.start ()) ## call(Juggling.end ())
クラス階層の合成
 composition advice の導入


複数のクラスを Joinpoint としてとる
Hyper/J[Ossherら’00]の記述を応用
composition() :
class(personnel.*) ## class(payroll.*) {
mergeByName;
override String $2.name()
with String $1.name();
String $composed.toString() {
StringBuffer ret = new StringBuffer();
for (int i = 0; i < $result.length; ++i)
ret.append($result[i]);
return ret.toString();
}
}
Composition Advice
 mergeByName;
 何も指定されなければ同じ名前のメソッドを結合
 結合後のメソッドは合成前のクラスのメソッドを順番に呼び
出し最後の呼び出しの結果を返り値とする
 override String $2.name() with String $1.name();
 name()メソッドは結合せずに二番目のjoinpointのメソッド
を呼び出す
 $1,$2はpointcutによって得られたjoinpoint配列の要素
 String $composed.toString() { … }
 結合されたtoString()の返り値を再構成する
実装
 拡張可能なコンパイラ


pointcut および advice を Java で追加可能
Polyglot, Javassistを用いて作成
 コンパイル速度の比較

PureTLS Toolkits のコンパイルおよび合成


クラス数: 127個 行数: 約18000行
joinpoint: 6384個 うち合成対象箇所: のべ1052個
単位はms
juggler
javac1.5
ajc1.2
abc1.0
Aspect無し
18601
2972
4443
23101*
Aspect有り
19019
5317
N/A
*内部エラーにより終了(バイトコード変換で問題発生)
関連研究
 Hyper/J



異なるモジュールの合成を行うアスペクト指向シ
ステム
メソッド、フィールド、クラスを既存のモジュールか
ら切り出し他のモジュールに合成を行う
自由度が高い反面、ユーザーが面倒を見なけれ
ばならないところが多い
まとめ
 複数個のJoinpointの集合


pointcut式に連結演算子を導入
composition adviceによるクラス階層の合成
 今後の課題



pointcut による記述の柔軟性を生かし切れていない
advice での joinpointの扱いの整合性がとれていな
い
他の複数の joinpoint を必要とするアスペクトの記述
おしまい
質問用スライドに続く…
単一のJoinpointの限界③
人材管理::販売担当
名前()
表示()
役職()
性別()
Aspect
解雇()
給与台帳::販売担当
役職()
性別()
表示()
解雇()
備考()
名前()
備考()
一つ一つ記述する
 メソッド・フィールドごとに一つのアドバイスが必要
 保守が難しい
Hyper/Jによる解法
 特徴点の抽出
package personnel : Feature.Personnel
package payroll : Feature.Payroll
 その振る舞いの定義
relationships:
mergeByName;
override operation Feature.Payroll.name
with operation Feature.Personnel.name;
AspectJと何が違う?
特徴点 (Joinpoint) が二つある
AspectJ での実際のコード例
public aspect PersonnelWithPayroll perthis(this(personnel.Employee+)) {
private payroll.Employee payroll;
before(personnel.Employee personnel) :
execution(personnel.Employee+.new())
&& this(personnel) {
String name = personnel.getClass().getName();
name = nameのクラス名だけ取り出す;
payroll = Class.forName( “payroll.” +name).newInstance();
}
after(String name) :
execution(void personnel.Employee+.setName(String))
&& args(name) {
payroll.setName(name);
}
…
}