2013-07-05 13 views
5

Jak mogę ustawić adnotację jako argument dla porady zdefiniowanej dla adnotacji na poziomie klasy ? Czy to możliwe?@AspectJ Adnotacja na poziomie klasy Adnotacja z adnotacją jako argumentem metody

Ze stanowiska here jestem w stanie uzyskać cięcie punktowe, które identyfikuje całą publiczną metodę w klasie, która jest oznaczona określoną adnotacją. Jestem również w stanie uzyskać poradę. Jednak nie wiem, jak uzyskać zmienną adnotacji przekazane jako argument w powyższym przypadku.

Dla adnotacji na poziomie metody, jestem w stanie uzyskać punkt i poradę, w której mogę uzyskać adnotację przekazaną jako argument, ale nie wiem, jak osiągnąć to samo dla adnotacji na poziomie klasy.

Poniższy kod działa, ale muszę dostać adnotacji jako argument za radą „LogExecutionTimeByClass” w poniższym programie i nie mogłem w stanie uzyskać odpowiednią poradę lub punkt przekroju do tego samego.

Adnotacja:

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

@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface LogExecutionTime { 
String level(); 
} 

Aspekt: ​​

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

@Aspect 
public class LogTimeAspect { 

    /* 
    * Pointcut to match all the public methods. 
    */ 
    @Pointcut("execution(public * *(..))") 
    public void publicMethod() {} 

    /* 
    * Advice for the public methods that are marked with Annotation "LogExecutionTime" and it works as expected no issue. 
    */ 
    @Around("publicMethod() && @annotation(annotation) ") 
    public Object LogExecutionTimeByMethod(final ProceedingJoinPoint joinPoint,final LogExecutionTime annotation) throws Throwable 
    { 
     System.out.println("Invoking the method " +joinPoint.getSignature() +" by LogExecutionTimeByMethod Advice"); 
     return joinPoint.proceed(); 
    } 


    /* 
    * Pointcut to match all the public methods that are defined under the Class marked with Annotation LogExecutionTime. 
    */ 
    @Pointcut("within(@LogExecutionTime *)") 
    public void beanAnnotatedWithMonitor() {} 

    @Pointcut("publicMethod() && beanAnnotatedWithMonitor()") 
    public void publicMethodInsideAClassMarkedWithAtMonitor() {} 

    /* 
    * Below Advice works but I need the LogExecutionTime annotation as an argument to below method. (similar to the advice "LogExecutionTimeByMethod" 
    * defined above) 
    */ 
    @Around("publicMethodInsideAClassMarkedWithAtMonitor()") 
    public Object LogExecutionTimeByClass(final ProceedingJoinPoint joinPoint) throws Throwable 
    { 
     System.out.println("Invoking the method " +joinPoint.getSignature() +" by LogExecutionTimeByClass Advice"); 
     //System.out.println("Invoked by " + annotation.value()); //Need the Annotation Variable here as well... 
     return joinPoint.proceed(); 
    } 

/* 
    */ 
} 

przypisami Klasa:

@LogExecutionTime(level="Class_Level_Invocation") 
public class Operator { 

    @LogExecutionTime(level="Method_Level_Invocation") 
    public void operate() throws InterruptedException { 
     Thread.sleep(1000); 
    } 

    public void operate1() throws InterruptedException { 
     Thread.sleep(1000); 
    } 
} 

Program główny:

public class AspectJMain { 
    public static void main(String[] args) throws InterruptedException { 
      Operator op = new Operator(); 
      op.operate(); 
      op.operate1(); 
     } 
} 

wyjściowa:

Invoking the method void Operator.operate() by LogExecutionTimeByMethod Advice 
Invoking the method void Operator.operate() by LogExecutionTimeByClass Advice 
Invoking the method void Operator.operate1() by LogExecutionTimeByClass Advice 

Należy pamiętać, że przy użyciu Wiosna to nie jest opcja. Muszę użyć kompilatora AspectJ. Skompilowałem moje klasy i spakowałem je jako słoik i użyłem kompilatora ApsectJ do utkania aspektu za pomocą poniższego polecenia.

AJC -inpath core.jar -outjar .. \ lib \ core_woven.jar -1,5

Każda wskazówka byłoby pomocne.

Odpowiedz

12

Rozwiązanie jest całkiem proste. Piszę swój kod w macierzystym stylu AspectJ, wolę go dla jasności. Będziesz w stanie łatwo dostosować go do @AspectJ stylu adnotacji:

public aspect LogTimeAspect { 
    pointcut publicMethod() : execution(public * *(..)); 

    before(LogExecutionTime logAnn) : publicMethod() && @annotation(logAnn) { 
     System.out.println(thisJoinPointStaticPart + " -> " + logAnn.level()); 
    } 

    before(LogExecutionTime logAnn) : publicMethod() && @within(logAnn) { 
     System.out.println(thisJoinPointStaticPart + " -> " + logAnn.level()); 
    } 
} 

Wyjście jest następująca:

execution(void Operator.operate()) -> Method_Level_Invocation 
execution(void Operator.operate()) -> Class_Level_Invocation 
execution(void Operator.operate1()) -> Class_Level_Invocation 

Jak widać,

  • nie ma potrzeby around() porady, before() jest wystarczające, chyba że chcesz manipulować dowolnymi parametrami lub zablokować wykonanie wykonanych metod,
  • możesz powiązać adnotacje, o których mowa, poprzez @annotation() lub @within() do nazwanych parametrów, jeśli po prostu użyjesz poprawnej składni.

Ciesz się!:-)


Aktualizacja: Oto wersja @AspectJ aspektu dla wygody i dlatego, że wydawało się, że problemy adaptacji moje rozwiązanie z natywnej składni:

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

@Aspect 
public class LogTimeAspect { 
    @Pointcut("execution(public * *(..))") 
    public void publicMethod() {} 

    @Around("publicMethod() && @annotation(logAnn)") 
    public Object LogExecutionTimeByMethod(ProceedingJoinPoint joinPoint, LogExecutionTime logAnn) throws Throwable { 
     System.out.println(joinPoint + " -> " + logAnn.level()); 
     return joinPoint.proceed(); 
    } 

    @Around("publicMethod() && @within(logAnn)") 
    public Object LogExecutionTimeByClass(ProceedingJoinPoint joinPoint, LogExecutionTime logAnn) throws Throwable { 
     System.out.println(joinPoint + " -> " + logAnn.level()); 
     return joinPoint.proceed(); 
    } 
} 

wyniki zostaną identyczny z moją oryginalną wersją.

+0

Dzięki. Pozwól mi wypróbować. Powodem Wokół jest uzyskanie czasu wykonania metody. – param83

+0

Próbowałem, ale nie udało mi się przekazać argumentu z adnotacją przez wewnątrz, ale poniżej wyciąć działa @Pointcut ("publicMethod() & & beanAnnotatedWithMonitor() &&annotation (adnotacja)") – param83

+0

Naprawdę nie potrzebujesz 'beanAnnotatedWithMonitor()', zobacz moja aktualizacja powyżej. – kriegaex