Load-time weavingで 広 がるAOPの 可 能 性 1
自 己 紹 介 名 前 : 木 村 聡 (きむら さとし) Seasarプロジェクトコミッタ: S2Struts S2Mai 舞 姫 仕 事 ( 株 )フルネス フレームワーク 自 動 生 成 ツール 2
これまで 書 いたものとか 書 籍 : Eclipseで 学 ぶはじめてのJava Seasar 入 門 ~はじめてのDI&AOP~ 雑 誌 Web 記 事 CodeZine DB Magazine WEB+DB Seasar2 徹 底 攻 略 (Vol.31) JavaWorld 開 発 者 にとって 易 しく 優 しい 軽 量 コンテナ Seasar2の 実 力 を 探 る (2005/05) 3
はじめに AOPの 乱 用 禁 止 4
AOPとは Aspect Oriented Programの 略 日 本 語 では アスペクト 指 向 プログラム ソフトウェアの 複 雑 さの 低 減 や 再 利 用 性 を 向 上 させる よく 使 われる 機 能 ログ 例 外 処 理 トランザクション 認 証 処 理 RPC 障 害 対 応 S2プロダクトだと S2Dao 5
簡 単 に 言 うと AOPの 仕 組 みを 使 うと 後 から 機 能 や 処 理 を 挿 入 することができるよ うになる 6
例 public String hello(string arg) { Strimg message = "Hello " + arg; System.out.println(message); return message; } 実 行 Hello World 7
例 public String hello(string arg) { Strimg message = "Hello " + arg; System.out.println(message); return message; } AOP 使 って 実 行 + 設 定 ファイル など 2009-03-14 17:00.00 BEGIN hello("world") Hello World 2009-03-14 17:00.01 END hello("world") : "Hello World" 8
AOPのメリット 生 産 性 の 向 上 共 通 処 理 を 記 述 しなくても 良 い 品 質 の 向 上 共 通 処 理 の 埋 め 込 み 忘 れが 減 る アノテーションの 処 理 を 組 み 込 みやすい 9
よく 見 かける 文 章 AOPを 使 って アプリケーションのソースコードを 一 切 変 更 す ることなく します 10
Struts Only このStrutsで 作 られたシステムに AOPでTraceを 出 してくれ 11
Struts Only 将 軍 様 Seasarで 作 り 直 してください そうしたら 出 来 ます 12
AOPは 適 用 が 難 しい クラスの 書 き 換 えが 必 要 コンパイル 時 に 書 き 換 える ツール/ 文 法 が 難 しい Java 以 外 の 言 語 ツールを 覚 える 必 要 がある AspectJとか 13
これまでの 条 件 SeasarなどAOPの 仕 組 みが 提 供 されているフ レームワークを 使 っていれば 出 来 る AspectJなどを 使 う 場 合 コンパイルし 直 せば 出 来 る AOPとDIコンテナは 相 性 が 良 い DIコンテナのメリット 14
深 いところには 手 が 届 かない Strutsとかライブラリの 中 のクラス ライブラリもコンパイルしなおせばOK 15
現 在 は できます 16
Demo 17
Demo S2のUtilクラスのシーケンス 図 を S2Javelinで 出 力 18
内 部 的 には バイトコードエンジニアリング Java5から 動 的 にバイトコードを 操 作 するた めの 枠 組 みが 提 供 されるようになった - javaagent クラスロード 時 に 操 作 可 能 実 行 時 コンパイル 時 ではなく JavaRebel Pleiades 19
できること メソッドに 仕 掛 ける privateも final,staticも コンストラクタに 仕 掛 ける 20
基 本 スペック AOP Alliance MethodInterceptor ConstructorInterceptor FieldInterceptor Java 標 準 javax.interceptor. AroundInvoke(AOP AllianceのMethodInterceptor) InvocationContext(AOP AllianceのInvocation) ExcludeClassInterceptors Interceptors 21
こんな 時 に 使 える バグFix 深 い 場 所 にあるクラスのログなど デバッグ 時 のtoString 個 人 の 生 産 性 を 高 める Unitテスト 戻 り 値 や 引 数 を 強 引 に 変 更 キャッシュ 22
こんな 時 に 使 える バグFix ライブラリのバージョンを 上 げたい でも アプリのコードがコンパイルエラーになるので 見 送 り 部 分 的 なパッチを 作 りAOPで 対 応 アプリのコードが 影 響 の 出 ないようにできる 23
使 用 方 法 1. jarを 配 置 2. java のオプション 指 定 java -javaagent:kimu-aop-core.jar foo.bar.main 3. 設 定 ファイルを 用 意 24
基 本 設 定 ファイル 解 説 ファイル 名 :aspect.xml Seasar2のdiconファイルを 意 識 対 象 となるクラスを 指 定 <aspect-config> <def target="org.apache.struts.action"> <aspect> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 機 能 (TraceInterceptorは ログ) 25
正 規 表 現 で 指 定 設 定 ファイル 解 説 正 規 表 現 も 可 能 <aspect-config> <def target="jp.co.foo.bar.*serviceimpl"> <aspect> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 26
メソッドの 指 定 設 定 ファイル 解 説 pointcutで 指 定 <aspect-config> <def target="jp.co.foo.bar.*serviceimpl"> <aspect pointcut="execute,tostring"> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 指 定 しない 場 合 は implメソッド Genericsも 対 応 27
メソッドの 指 定 設 定 ファイル 解 説 正 規 表 現 も 可 能 <aspect-config> <def target="jp.co.foo.bar.*serviceimpl"> <aspect pointcut=".*"> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 28
メソッドの 指 定 設 定 ファイル 解 説 notで 除 外 <aspect-config> <def target="jp.co.foo.bar.*serviceimpl"> <aspect pointcut=".*" not="tostring,hashcode"> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 29
設 定 ファイル 解 説 アクセス 修 飾 子 の 指 定 <aspect-config> <def target="jp.co.foo.bar.*serviceimpl"> <aspect modifier="private"> modifierで 指 定 指 定 した 修 飾 子 以 上 new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> public(デフォルト) protected package-private private 30
設 定 ファイル 解 説 Interceptorの 指 定 <def target="jp.co.foo.bar.*actionimpl"> <aspect> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> <def target="jp.co.foo.bar.*serviceimpl"> <aspect> jp.dodododo.aop.interceptors.traceinterceptor.getinstance() </aspect> </def> Javaのコードを 1ステートメントで 記 述 31
設 定 ファイル 解 説 優 先 度 上 に 書 いてある 方 が 優 先 <aspect-config> <def target="jp.co.foo.bar.bazserviceimpl"> <aspect> new jp.dodododo.aop.interceptors.simpletraceinterceptor() </aspect> </def> <def target="jp.co.foo.bar.*serviceimpl"> <aspect> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 32
設 定 ファイル 解 説 優 先 度 AOP 対 象 外 <aspect-config> <def target="org.apache.log4j.*" /> <def target="jp.co.foo.bar.*serviceimpl"> <aspect> new jp.dodododo.aop.interceptors.traceinterceptor() </aspect> </def> </aspect-config> 33
特 定 のメソッドを 対 象 外 にする Seasar2だと finalメソッドにする Interfaceからメソッドを 除 く pointcutで 頑 張 る public final String hello(string arg) { Strimg message = "Hello " + arg; System.out.println(message); return message; } 34
特 定 のメソッドを 対 象 外 にする kimu-aop Enhanceアノテーションで 指 定 ExcludeClassInterceptorsアノテーションで 指 定 (notで 指 定 ) 無 限 ループしないように 自 作 のインターセプタとかに 付 ける @Enhance(false) public String hello(string arg) { Strimg message = "Hello " + arg; System.out.println(message); return message; } 35
特 定 のメソッドを 対 象 外 にする kimu-aop Enhanceアノテーションで 指 定 ExcludeClassInterceptorsアノテーションで 指 定 (notで 指 定 ) @ExcludeClassInterceptors public String hello(string arg) { Strimg message = "Hello " + arg; System.out.println(message); return message; } 36
用 意 しているInterceptor お 約 束 (S2AOPと 同 じ) ログ 系 TraceInterceptor SimpleTraceInterceptor ThrowsInterceptor 同 期 TraceThrowsInterceptor SyncInterceptor 37
用 意 しているInterceptor 独 自 TraceWithCustomLoggerInterceptor TakeOverInterceptor CommonsBuilderInterceptor ToStringInterceptor CloneInterceptor 38
TraceWithCustomLoggerInterceptor クラス 単 位 でTraceログの 設 定 が 可 能 log4j.properties 39
TakeOverInterceptor Interceptorに 定 義 しているメソッドにシグネ チャが 同 じメソッドがあれば そのメソッドを 実 行 40
CommonsBuilderInterceptor Objectクラスメソッドの 実 装 public class CommonsBuilderInterceptor extends TakeOverInterceptor { public String tostring() { Object target = getthis(); return ToStringBuilder.reflectionToString(target); } public int hashcode() { Object target = getthis(); return HashCodeBuilder.reflectionHashCode(target); } public boolean equals(object obj) { Object target = getthis(); return EqualsBuilder.reflectionEquals(target, obj); } } 41
ToStringInterceptor 配 列 などに 対 応 42
CloneInterceptor シリアライズ デシリアライズ 43
S2AOPとの 違 い エンハンスしたクラス S2AOP: 対 象 のクラスを 継 承 したクラス KimuAop: 対 象 のクラスそのもの ターゲットのクラス 取 得 の 作 法 が 異 なる( 独 自 のInterceptorを 作 る 場 合 に 注 意 かも) InterceptorはSingletonでない 定 義 時 にgetInstance()とか 書 けばOK インターフェースを そのままインスタンス 化 できない ex:s2dao 44
今 後 Unitテスト 用 の 仕 組 みを 提 供 ( 今 もあるけど 変 更 する 予 定 ) 45
プロダクト 情 報 名 前 Kimu-aop URL http://code.google.com/p/kimu-aop/ 46
まとめ AOPの 乱 用 禁 止 kimu-aop ほぼ 何 でも 出 来 る いままでリーチできなかったクラスにリーチ S2AOPとの 違 いに 注 意 47
終 わり ご 清 聴 ありがとうございました 48