S2サポーター (2006-04-29 (土) 16:32:41)
Question
diconファイルで、OGNL式で取得したコンポーネントに対して
アスペクトを適用するように記述することは可能でしょうか?
以下のように書きたかったのですが、エラーになります。
<component> @hogeFactory @ HOGE <aspect>hogeInterceptor</aspect> </component>
Answer
できません.
S2AOP は,元のクラスを継承したサブクラスを作成します.
アスペクトが適用されるのはそのサブクラスのインスタンスに
なります.
OGNL で取得したコンポーネントはすでにインスタンス化されて
しまっており,S2AOP が作成したサブクラスのインスタンスでは
ないためアスペクトは適用されません.
DelegateInterceptor を使えばやりたいことが
できるかもしれません.
<component class="..."> <aspect>hogeInterceptor</aspect> <aspect> <component class="org.seasar.framework.aop.interceptors.DelegateInterceptor"> <property name="target">@hogeFactory @ HOGE</property> </component> </aspect> </component>
一番外側の <component> 要素には class 属性を指定する必要があります.
インタフェースを指定しても構いません.このコンポーネントを取得してメソッドを呼び出すと,
最初に hogeInterceptor が適用され,その後にDelegateInterceptor が適用されます.
DelegateInterceptor は target プロパティに指定されたコンポーネントに委譲します (同じメソッドを呼び出します).
当然ですが,コンテナから取得したコンポーネントのメソッドを呼び出さないとアスペクトは適用されません.
hogeFactory.HOGE のメソッドを呼び出してもダメです.参考投稿
http://ml.seasar.org/archives/seasar-user/2006-April/005405.html
http://ml.seasar.org/archives/seasar-user/2006-April/005408.html
Question
aspect (インターセプタ) のインスタンスモードを singleton 以外にすることはできますか?
インスタンスモードを request にして HttpServletRequest のプロパティを用意しましたが設定されません.
<component name="myInterceptor" instance="request" class="..."/> <component name="myComponent" class="..."> <aspect>myInterceptor</aspect> </component>
Answer
インターセプタに InterceptorLifecycleAdapter を適用してください
S2AOP は,元のクラスを継承したサブクラスを作成する際にインターセプタをコンテナから取得します.
このため,インターセプタのインスタンスモードが prototype や request であっても,コンテナの初期化時にインスタンス化されてしまい,HttpRequest や HttpSession を受け取ることができません.
このような場合には,インターセプタの instance 属性を prototype にした上で, InterceptorLifecycleAdapter を適用してください.
<include path="aop.dicon"/> <component name="myInterceptor" instance="prototype" class="..."> <aspect>aop.lifecycleAdapter</aspect> </component> <component name="myComponent" instance="request" class="..."> <aspect>myInterceptor</aspect> </component>
これにより,myInterceptor の invoke メソッドが呼ばれるたびに InterceptorLifecycleAdapter が myInterceptor をコンテナから取得して委譲します.
Client -> myInterceptor (コンテナ初期化時に取得) -> InterceptorLifecycleAdapter -> myInterceptor (毎回取得) -> myComponent
という呼び出しシーケンスになります.最初の myInterceptor と 後の myInterceptor は別のインスタンスになります (myInterceptor が singleton 以外の場合).
参考投稿
http://ml.seasar.org/archives/seasar-user/2005-December/000242.html
http://ml.seasar.org/archives/seasar-user/2005-December/000250.html