2011-01-26 6 views
1

ハウディ。私はSonic ESBでAspectJを使ってカスタムESBサービスのservice()メソッドへの呼び出しを傍受しようとしています。これは、私が事前にサービスクラスの種類を知らないことを意味します。私はそれがインターフェイスXQServiceExを実装していることだけを知っています。実装されたservice()メソッドは、JMSメッセージがサービスエンドポイントに到着するたびにSonicコンテナによって呼び出されます。しかし、コンテナはやや複雑な内部構造を持ち、各受信メッセージに対して3つのアドバイスが呼び出されています。 (私は私の専門用語があまりにも遠くではありません願っています。)Sonic ESBクラス階層により、望ましくない複数のアスペクトの呼び出しが発生する

私の局面は次のようになります。

package com.ncr.eai.esb.aop; 

import com.sonicsw.xq.XQService; 
import com.sonicsw.xq.XQServiceEx; 
import com.sonicsw.xq.XQServiceContext; 
import com.sonicsw.xq.XQServiceException; 
import com.ncr.eai.esb.*; 

aspect XQServiceAspect { 
final String id = "O : "; 

pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) : 
    call(void XQService.service(XQServiceContext)) && 
    target(svc) && 
    target(com.sonicsw.xq.XQService) && 
//  within(com.ncr..*) && 
    args(ctx); 

    before(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) { 
    System.out.println(id + "Entering XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this); 
    } 

    void around(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) { 
    System.out.println(id + "In the around() advice before call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this); 
    proceed(svc, ctx); 
    System.out.println(id + "In the around() advice after call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this); 
    } 


    after(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx) returning: serviceCall(svc, ctx) { 
    System.out.println(id + "Returned from XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this); 
    } 
} 

出力は次のようになります。

O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] [email protected] [email protected] 
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] [email protected] [email protected] 
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.so[email protected]195638a co[email protected]19c705e [email protected] 
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.so[email protected]195638a co[email protected]19c705e [email protected] 
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] co[email protected]19c705e [email protected] 
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] co[email protected]19c705e [email protected] 
    >>>> Inside of the actual service() method! 
    >>>> About to exit the actual service() method! 
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] co[email protected]19c705e [email protected] 
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] co[email protected]19c705e [email protected] 
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.so[email protected]195638a co[email protected]19c705e [email protected] 
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.so[email protected]195638a co[email protected]19c705e [email protected] 
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] [email protected] [email protected] 
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) [email protected] [email protected] [email protected] 

私は私の実験の結果を知っていますここでは読みにくいですが、service()を呼び出すと、com.sonicsw.xqimpl.service.XQServiceChaincom.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper、およびcom.ncr.eai.esb.ServiceFromAspectの3つのコールが発生します。メッセージごとに1つのコールしか表示されません。つまり、service()への1回のコールです。そして、私は第三のクラスの名前が何であるかを事前に知らない。このテストはcom.ncr.eai.esb.ServiceFromAspectという名前のカスタムサービスで実行されていますが、XQServiceExを実装する他にも数十のサービスがあり、ハードコードする必要はありません。実行時に発見する必要があります。コメントアウトしたwithin(com.ncr..*)というフレーズを追加しようとしましたが、それを使ってポイントカットが全くできなくなりました。私は!within(com.sonicsw..*)のようなものでcom.sonicswパッケージを除外しようとしましたが、すべてのポイントカットが機能しなくなりました。

デプロイメントが行われる限り、私はこの問題を解決するために、コンテナのコマンドラインにjavaagentを追加してロード時のウィービングを行っています。全体的な戦略は機能していますが、私は希望どおりに動作するポイントカットを構築しようとするよりも長い時間を費やしました。

メッセージごとに1つのコールを取得するにはどうすればよいですか。

"アドバイス"ありがとうございます!

おかげで、 リーグレー、SOAアーキテクト NCR

答えて

2

それはそこで起こっDecoratorパターンのように見えます。装飾された通話のアドバイスを避けるには、おそらくcflowbelow()を使用するだけです。

pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) : 
    call(void XQService.service(XQServiceContext)) && 
    target(svc) && 
    target(com.sonicsw.xq.XQService) && 
    args(ctx) && 
    !cflowbelow(call(void XQService.service(XQServiceContext))); 
+0

恐ろしい、ありがとう! –

+0

aspectj-usersメーリングリストでは、cflowがすべてのサイトを計測し、コントロールフローを確認するためのチェックを行うため、パフォーマンスの影響がより大きくなると言われました。 1つのサイトだけが製織時に装備されるため、 'withincode(* * .service(XQServiceContext))'はもう少しパフォーマンスが良いことが示唆されました。あなたのやり方は絶対にうまくいきますが、私はこれについてもあなたに知らせるべきだと思いました。 –

関連する問題