2013-05-17 4 views
7

私はSpring 3.1.2.RELEASEをcglibの読み込み時に使用しています。カスタムの注釈と注釈付きのパラメータを持つメソッドで作業するためのアドバイスを得ようとしています。注釈付きパラメータを使用してSpring AOPのアドバイスに引数を渡すにはどうすればよいですか?

アドバイス:

@Aspect 
public class MyAdvice 
{ 
    @Around("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) " + 
    "&& args(batch) && @args(propertyToLock)" 
    public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch, LockVal propertyToLock) throws Throwable { 
     //Do stuff.... 
     pjp.proceed(); 
    } 
} 

ここでは、私がテストしていたクラスです:

public interface UpdateManager 
{ 
    public void processUpdate(MyBatchObject batch); 
} 


public class UpdateManagerImpl implements UpdateManager 
{ 
    @Lock 
    public void processUpdate(@LockVal("lockValue") MyBatchObject batch) 
    { 
     //Do stuff... 
    } 
} 

問題は、私は実行するためのアドバイスを得ることができないということです。私がポイントカット内の@argsとargs条件を削除した場合、アドバイスが起動しますが、必要なパラメータを取得するためにProceedingJoinPointを調べなければなりません。

アドバイスが起動しないのはなぜですか?私は間違ったことをしましたか?

編集:以下のポイントカットは、春とスタンドアロンプ​​ログラムとして作業を行います:

@Aspect 
public class MyAdvice 
{ 
    @Around("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) " + 
    "&& args(batch)" 
    public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch) throws Throwable { 
     //Do stuff.... 
     pjp.proceed(); 
    } 
} 

しかし、それはロード時ウィービングを使用したJBoss 6の下では動作しません。私は私の質問が、なぜ、JBoss 6ではなく、スタンドアローンのプログラムとして機能するのだろうと思いますか?

+0

私はこれが古いと知っていますが、未回答のままです。適切と思われる場合は、私の答えを受け入れてupvoteしますか?ありがとう。 – kriegaex

+0

私はそのプロジェクトから今に移行しましたが、どのようにコードを実行してもコードは機能しないと言えるでしょう。以前のバージョンとは異なる、JBoss 6のフラットクラスローダー+ cglibと関係がありました。 – Brad

答えて

1

これは解決策ではなく、さらに一歩あなたを取る必要があります。

私はあなたがおそらく@Aspectなく@Adviceを意味し、あなたがあなたの注釈にタイプミスをしたと仮定していますか?

a:私が持っている提案は、これらを試してみることです:

名前付きのポイントカットと、ポイントカットに適用するアドバイスを分ける:

@PointCut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) && args(batch) && @args(propertyToLock)") 
public void mypointcut(Object batch, LockVal propertyToLock){} 

@Around("mypointcut(batch, propertyToLock)" 
public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch, LockVal propertyToLock) throws Throwable { 
    //Do stuff.... 
    pjp.proceed(); 
} 

b。 argsの表現かという表現が問題を引き起こしている可能性があります.1つを保ち、他のものを取り除き、どの組み合わせがうまくいくかを見てください。

c。

@PointCut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) && args(batch) && @args(propertyToLock) && argNames="batch,test1,test2") 
public void mypointcut(Object batch, LockVal propertyToLock){} 
+0

'args()'でパラメータの注釈をバインドすることはできません。私自身の答えを見てください。 – kriegaex

+0

私はa)とb)を試してみました。私は今c)のテストに取り組んでいます - 提案に感謝! – Brad

+1

ポイントカットを試みたとき: 'execute(@ com.mycompany.locking.Lock * *)@ && args(バッチ)&& argNames(バッチ\ エラー時にエラーが発生しました::複数のバインディング0、BindingTypePattern(java.lang.Object、0) ' – Brad

2

:これは狭いない事をダウンした場合は、もう一つのオプションは、明示的にもargNames式を追加することができ、それは、引数名が一掃されていると、実行時に名前で、最大一致していないことが考えられます更新:@args()はパラメータの注釈と一致するものではなく、パラメータタイプの注釈であることを忘れています。これはあなたが望むものではないため、ここでは使用しません。


args()でパラメータの注釈をバインドすることはできません。パラメータ自体はバインドできません。つまり、リフレクションを介してパラメータの注釈にのみアクセスできます。メソッドのシグネチャを決定し、そこからオブジェクトMethodを作成し、メソッドのパラメータの注釈を反復処理する必要があります。ここでは完全なコードサンプルは次のとおりです。

package com.mycompany.locking; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface Lock {} 
package com.mycompany.locking; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.PARAMETER) 
public @interface LockVal { 
    String value() default ""; 
} 
package com.mycompany; 

public class MyBatchObject {} 
package com.mycompany; 

public interface UpdateManager { 
    public void processUpdate(MyBatchObject batch); 
} 
package com.mycompany; 

import com.mycompany.locking.Lock; 
import com.mycompany.locking.LockVal; 

public class UpdateManagerImpl implements UpdateManager { 
    @Lock 
    @Override 
    public void processUpdate(@LockVal("lockValue") MyBatchObject batch) { 
     System.out.println("Processing update"); 
    } 

    public static void main(String[] args) { 
     UpdateManager updateManager = new UpdateManagerImpl(); 
     updateManager.processUpdate(new MyBatchObject()); 
    } 
} 
package com.mycompany.aop; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Pointcut; 
import org.aspectj.lang.reflect.MethodSignature; 

import com.mycompany.MyBatchObject; 
import com.mycompany.locking.LockVal; 

@Aspect 
public class MyAspect { 
    @Pointcut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal (*), ..)) && args(batch)") 
    public void lockedMethod(MyBatchObject batch) {} 

    @Around("lockedMethod(batch)") 
    public Object lockAndProceed(ProceedingJoinPoint pjp, MyBatchObject batch) throws Throwable { 
     System.out.println(pjp); 
     System.out.println(batch); 
     MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); 
     Class<?> clazz = methodSignature.getDeclaringType(); 
     Method method = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes()); 
     LockVal propertyToLock; 
     for (Annotation ann : method.getParameterAnnotations()[0]) { 
      if(LockVal.class.isInstance(ann)) { 
       propertyToLock = (LockVal) ann; 
       System.out.println(propertyToLock.value()); 
      } 
     } 
     return pjp.proceed(); 
    } 
} 

私はUpdateManagerImpl.mainを実行すると、私は期待と同じように、次の出力を参照してください。

execution(void com.mycompany.UpdateManagerImpl.processUpdate(MyBatchObject)) 
[email protected] 
lockValue 
Processing update 

免責事項:私はSpringの人ではありません。Spring AOPではなくAspectJでテストしました。

+0

@argsの意味は何ですか?私は、パラメータの注釈とパラメータ型の注釈の違いを理解しているかどうかはわかりません。 – Brad

+0

また、私は、 '@ args'をポイントカットから完全に削除しようとしましたが、ポイントカットはまだ実行されません。 'args()'の条件は、それらの条件を両方とも削除するとポイントカットが期待通りに実行されるため、何らかの理由で失敗する原因になります。 – Brad

+0

ちょうど私のコードを使用して、それは動作します。 '@ args'に関しては、パラメータ' MyType foo'をキャッチすると、 '@ args'は、メソッドパラメータではなく、クラス' MyType'で宣言されたアノテーションにのみ一致します。 – kriegaex

関連する問題