2013-05-17 12 views
7

Sto usando Spring 3.1.2.RELEASE con cglib in fase di caricamento e sto cercando di ottenere consigli per lavorare con un metodo che ha annotazioni personalizzate e parametri annotati.Come si passano gli argomenti al consiglio Spring AOP con i parametri annotati?

Consigli:

@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(); 
    } 
} 

Qui è la classe che sto testando:

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


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

Il problema è che non riesco a ottenere la consulenza da eseguire. Se rimuovo le condizioni @args e args nel pointcut, il consiglio scatta, ma poi devo scavare attraverso il ProceedingJoinPoint per ottenere il parametro di cui ho bisogno.

Perché non viene attivato il consiglio? Ho fatto qualcosa di male?

Edit: Il seguente pointcut funziona come programma autonomo con la primavera:

@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(); 
    } 
} 

Tuttavia, non funziona in JBoss 6 usando la tessitura load-time. Suppongo che la mia domanda dovrebbe essere, quindi, perché funziona come un programma autonomo ma non sotto JBoss 6?

+0

So che questo è vecchio, ma ancora elencato come senza risposta. Vorresti accettare e revocare la mia risposta se mi sembra opportuno? Grazie. – kriegaex

+0

Ora sono passato da quel progetto, ma posso dire che il codice non ha mai funzionato, indipendentemente da come l'ho eseguito. Ricordo che aveva qualcosa a che fare con il flatloader + cglib in JBoss 6, che differiva dalle versioni precedenti. – Brad

risposta

1

Questa non è una soluzione, ma dovrebbe prendere un ulteriore passo avanti:

Io parto dal presupposto che hai fatto un errore di battitura nei tuoi annotazioni, probabilmente significava @Aspect e non @Advice?

Il suggerimento che ho potrebbe essere quella di provare questi:

a. Separare fuori in tagli denominati punti e il consiglio che si desidera applicare sulla pointcut:

@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. Potrebbe essere che l'espressione args o l'espressione @args stia causando il problema: prova a mantenerne una e rimuoverne altre e vedere quale combinazione funziona.

c. Se questo non fa le cose non strette verso il basso, un'opzione più potrebbe essere quella di aggiungere in modo esplicito un argNames espressione anche, potrebbe essere che i nomi degli argomenti vengono puliti fuori e non essere abbinati al nome in fase di esecuzione:

@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

Non è possibile associare l'annotazione di un parametro tramite 'args()', solo il parametro stesso. Vedi la mia risposta. – kriegaex

+0

Ho provato a) eb) senza successo. Sto lavorando alla prova c) ora - grazie per il suggerimento! – Brad

+1

Quando ho tentato il pointcut: 'execute (@ com.mycompany.locking.Lock * * (@ com.mycompany.locking.LockVal (*))) && args (batch) && argNames (\" batch \ ")' Ho ricevuto l'errore 'error at :: 0 multiple bindings0, BindingTypePattern (java.lang.Object, 0)' – Brad

2

Aggiornamento: Ho dimenticato di menzionare che lo @args() non è inteso per abbinare l'annotazione di un parametro, ma l'annotazione di un tipo di parametro, che non è ciò che si desidera e che quindi non uso qui.


Non si può legare l'annotazione di un parametro mediante args(), solo il parametro stesso. Ciò significa che puoi accedere all'annotazione del parametro solo tramite riflessione. È necessario determinare la firma del metodo, creare un oggetto Method da esso e quindi scorrere le annotazioni dei parametri del metodo.Ecco un esempio di codice completo:

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(); 
    } 
} 

Quando eseguo UpdateManagerImpl.main, vedo il seguente output, proprio come previsto:

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

Disclaimer: Non sono un ragazzo di primavera, l'ho appena testato con AspectJ, non Spring AOP.

+0

Posso chiedere per favore, cosa significa @args, quindi? Non sono sicuro di aver compreso la differenza tra l'annotazione sul parametro e l'annotazione sul tipo di parametro. – Brad

+0

Inoltre, ho tentato di rimuovere '@ args' dal pointcut del tutto, ma il pointcut non è ancora eseguito. Qualcosa sulla condizione 'args()' sta causando un errore, perché quando rimuovo entrambe le condizioni, il pointcut si esegue come previsto. – Brad

+0

Basta usare il mio codice, funziona. Per quanto riguarda '@ args', se si cattura un parametro' MyType foo', '@ args' corrisponde solo a un'annotazione dichiarata sulla classe' MyType', non sul parametro method. – kriegaex

Problemi correlati