Web アプリをユーザー毎に カスタマイズ可能にする AOP フレームワーク 東京工業大学 情報科学科4年 千葉研究室 戸部 敦
ユーザー毎にカスタマイズ可能なWebアプリ 新しい機能やスタイルを追加 知識のあるユーザーが高度な機能を組み込める 他のユーザーとの差をつけられる 例) FC2 ブログ 自分だけのページを作成できる よく使うコンテンツを配置して利便性を向上 例) my Rakuten, My Yahoo! サイトの集客に影響
カスタマイズの自由度 Web アプリ開発者が提供 利用者が自由にカスタマイズ どの範囲でサポートするかは状況次第 パラメータ ページのスタイルを変更(色、フォント・サイズ) プログラム・モジュール 開発者が用意する機能の中から選択 利用者が自由にカスタマイズ 新しいプログラム・モジュールをアップロードして利用 セキュリティ対策が必要 どの範囲でサポートするかは状況次第
現状:プラグイン機構の利用 プラグイン機構 実装コスト 拡張ポイントの制限 拡張ポイントを公開 設定ファイルに拡張ポイントで使われるクラスを記述 実装コスト Web アプリ毎にプラグイン機構を個別に実装する必要があり面倒 DI コンテナは実装コストを軽減 コンテナのコーディング規則に従う必要あり 拡張ポイントの制限 Web アプリ開発時に決めた拡張ポイント 以外はカスタマイズ不可能 interface Style { String table(String[][] data); } <config> <Style class=“StyleImpl” /> </config> class StyleImpl impl. Style { String table(String[][] data) { ... String html = webApp.style.table(data);
ユーザー単位のプラグイン機構 単純なプラグイン機構だけでは実現できない 例) ユーザー毎にスタイルを変更可能なコード ユーザー毎に読み込む設定が異なる 一般的な DI コンテナでは提供されない 例) ユーザー毎にスタイルを変更可能なコード 明示的な切り替えが必要。コードが不自然。 String html = webApp.getStyle(uid).table(data); String html = webApp.style.table(data); Aさん用の設定(uid=“A”) Bさん用の設定(uid=“B”) <config> <Style class=“StyleImplA” /> </config> <config> <Style class=“StyleImplB” /> </config>
開発したフレームワーク AOP 言語でカスタマイズ部分を記述 Per-session weaving ユーザーのアスペクトを登録する API 開発時に拡張ポイントを決定する必要がない 開発中に予期しない部分も拡張可能 元のソースコードを変えなくて良い Per-session weaving ユーザー単位のカスタマイズ機構を実現 セッションを見てユーザー毎に異なるアスペクトを適用 ユーザーのアスペクトを登録する API Web アプリ開発者が利用
AOP (アスペクト指向プログラミング) Weave 横断的関心事をモジュール化するプログラミング技法 アスペクト:新しいコードの内容とそれを実行する場所の組 Weave アスペクトを適用して元のコードの挙動を変更すること 元のソースコードの修正は不要(上書きされる) 開発時に見落とした拡張ポイントも変更可能 webApp. .table(data); class HtmlRenderer { String table(String[][] data) { ... } } style weave 後の weave 出力 @Glue class Customizer { @Around(“{ return HTMLコード; }") Pointcut pc = Pcd.call(“table(..)”); } 名前 カナ 敦 アツシ 滋 シゲル 名前 カナ 敦 アツシ 滋 シゲル
Per-session weaving の考案 ユーザー毎に異なるアスペクトを weave セッションからユーザーの識別子を取得 ユーザー毎に異なるクラスローダを使用 他のユーザーに影響を与えない Web アプリでユーザー毎に処理を明示的に分ける必要がない Aさんのアスペクト webApp.getStyle(uid).table(data); (処理A); webApp.style.table(data); (処理B); @Glue class CustomizerA { @Around(“return (処理A)”) } weave フレームワーク Bさんのアスペクト セッションに応じて weave するアスペクトを 自動的に振り分ける @Glue class CustomizerB { @Around(“return (処理B)”) }
処理の流れ 予めアスペクトを登録しておく リクエストを処理するときにセッションを取得 セッションに保存された識別子に応じてアスペクトを weave サーバー フレームワーク Webアプリ アスペクトを登録 リクエストの処理 セッションを取得 weave 実行 ロード weave された Web アプリを
実装 フレームワークを開発 サンプルアプリを作成 他のユーザーに影響を与えないことを確認
実装 Aさんのアスペクトを設定
実装 Aさんのアスペクトを weave した サンプルページ
実装 Bさんのアスペクトを設定
実装 Bさんのアスペクトを weave した サンプルページ
フレームワークの構成 サーバープログラムとして Tomcat を使用 AOP 言語として GluonJ を採用 Java で書かれた Web サーバー 設定ファイルでフレームワークを有効化 AOP 言語として GluonJ を採用 Java 文法内でアスペクトを記述 OS Java Tomcat フレームワーク GluonJ Web アプリ
関連研究 プラグイン機構 Load-time weaving Dynamic weaving AOP を使用しないカスタマイズ機構 カスタマイズが予め予測された拡張ポイントに限られる Web アプリでユーザー毎に読み込む設定を変更する必要 Load-time weaving クラスをロードする時にアスペクトを weave ユーザー毎に異なるアスペクトを weave できない Dynamic weaving プログラム実行中にアスペクトを weave アスペクトによるカスタマイズが制限される 新たなフィールドやメソッドを追加できない
まとめ ユーザー毎にカスタマイズ可能な Web アプリの開発フレームワーク 従来手法 フレームワークの実装 AOP 言語の利用 Per-session weaving の考案 従来手法 プラグインを Web アプリ毎に実装する必要 開発時に決めた拡張ポイント以外はカスタマイズ不可能 ユーザー毎に明示的に処理を分ける必要 フレームワークの実装 サンプルアプリを作成し動作を確認 実装コスト大!!
今後の課題 パフォーマンスの向上と検証 セキュリティ対策 クラスローダの親子関係を用いる キャッシュを使用 カスタマイズ不可なクラスは親ローダーでロード 親ローダーは最初のリクエストでのみ作成 キャッシュを使用 訪問者が少ないときに有効 アスペクトの weave によるオーバーヘッドを計測 セキュリティ対策 サーバー上のファイルを不正に読み込むなど Java アプレットと同等の対策を取る
おしまい ご清聴ありがとうございました。
複数アスペクトの weave 現在は単一のアスペクトのみサポート 複数のアスペクトを weave するには? 登録したアスペクトから他のアスペクトを読み込む場合は GluonJ の実装に依存 複数のアスペクトを weave するには? 共通部分が存在した場合ユーザーに警告を表示 登録されているアスペクトが 挙動を変更する箇所 登録するアスペクトが 挙動を変更する箇所
クラスローダでの効率化 AOP クラスローダ AppLib クラスローダ アスペクトを weave するクラスローダ(現在)