複数個の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); } … }
© Copyright 2024 ExpyDoc