2013-05-17 15 views
7

Używam Spring 3.1.2.RELEASE z tkaniem czasu ładowania cglib i staram się uzyskać porady do pracy z metodą, która ma niestandardowe adnotacje i parametry z adnotacjami.Jak przekazywać argumenty do porady Spring AOP z przypisanymi parametrami?

Wskazówka:

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

Oto klasa I 'm testowania:

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


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

Problem polega na tym, że nie mogę dostać rada wykonać. Jeśli usunę warunki @args i args w pointcut, podpowie się, ale muszę przekopać się przez ProceedingJoinPoint, aby uzyskać parametr, który jest mi potrzebny.

Dlaczego nie ma porady? Czy zrobiłem coś nie tak?

Edit: Poniższy punkt przekroju działa jako samodzielny program z wiosny:

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

Jednak to nie działa pod JBoss 6 stosując obciążenie w czasie tkania. Przypuszczam, że moim pytaniem powinno być zatem, dlaczego działa jako samodzielny program, ale nie pod JBoss 6?

+0

Wiem, że ten jest stary, ale wciąż jest wymieniony jako nieodebrany. Czy mógłbyś zaakceptować i przyjąć moją odpowiedź, jeśli wydaje się to właściwe? Dzięki. – kriegaex

+0

Przeniosłem się teraz z tego projektu, ale mogę powiedzieć, że kod nigdy nie działał, bez względu na to, jak go uruchomiłem. Jak pamiętam, miało to coś wspólnego z płaskim programem ładującym classloader + cglib w JBoss 6, który różni się od poprzednich wersji. – Brad

Odpowiedz

1

To nie jest rozwiązanie, ale powinno Ci krok dalej:

jestem zakładając, że popełnił literówkę w adnotacji, to prawdopodobnie oznaczało @Aspect i nie @Advice?

Sugestia, że ​​mam byłoby wypróbować te:

a. Oddziel się na nazwane cięcia punktowe i porady, które chcesz zastosować do cięcia punktowego:

@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. Może to oznaczać, że wyrażenie: args lub wyrażenie @args powoduje problem - spróbuj go zachować, usuwając inne i zobacz, która kombinacja działa.

c. Jeśli to nie wąskie rzeczy w dół, jeszcze jedna opcja może być jawnie dodać wyrażenie argNames też może się zdarzyć, że nazwy argumentów są czyszczone i nie są dopasowane z nazwy w czasie wykonywania:

@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

Nie można powiązać adnotacji parametru za pomocą 'args()', tylko sam parametr. Zobacz moją własną odpowiedź. – kriegaex

+0

Próbowałem a) ib) bez powodzenia. Pracuję nad testowaniem c) teraz - dzięki za sugestię! – Brad

+1

Kiedy podjąłem próbę cięcia: 'execute (@ com.mycompany.locking.Lock * * (@ com.mycompany.locking.LockVal (*))) && args (batch) && argNames (\" batch \ ")' Otrzymałem błąd 'error at :: 0 multiple bindings0, BindingTypePattern (java.lang.Object, 0)' – Brad

2

Aktualizacja: Zapomniałem wspomnieć, że @args() nie jest dopasowane do adnotacji parametru, ale adnotacja typu parametru, która nie jest tym, czego potrzebujesz i której w związku z tym nie używam tutaj.


Nie może się wiązać adnotacji parametr za pośrednictwem args() tylko parametru. Oznacza to, że dostęp do adnotacji parametru można uzyskać tylko za pomocą odbicia. Należy określić podpis metody, utworzyć z niego obiekt Method, a następnie powtórzyć adnotacje parametrów metod.Oto pełna przykładowy kod:

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

Kiedy biegnę UpdateManagerImpl.main, widzę następujące dane wyjściowe, tak jak oczekiwano:

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

Nota prawna: Nie jestem facetem wiosennym, właśnie przetestowałem to z prostym AspectJ, a nie Spring AOP.

+0

Czy mogę zapytać, do czego służy @args, a następnie? Nie jestem pewien, czy rozumiem różnicę między adnotacją na parametrze a adnotacją na typie parametru. – Brad

+0

Próbowałem również całkowicie usunąć '@ args', ale wycinek nadal nie jest wykonywany. Coś w warunku 'args()' powoduje niepowodzenie, ponieważ po usunięciu obu tych warunków punktowanie wykonuje się zgodnie z oczekiwaniami. – Brad

+0

Po prostu użyj mojego kodu, działa. Jeśli chodzi o '@ args', jeśli przechwycisz parametr' MyType foo', '@ args' odpowiada tylko adnotacji zadeklarowanej dla klasy' MyType', a nie parametru metody. – kriegaex

Powiązane problemy