2013-07-05 67 views
5

如何獲得註釋作爲參數爲 級別註釋定義的參數傳遞?可能嗎?@AspectJ類級別註釋建議與註釋作爲方法參數

從帖子here我能夠得到標識所有公共方法的標記由特定註釋標記的切點。我也能夠得到建議。但是,我不知道如何在上面的情況下獲取作爲參數傳遞的註釋變量。

對於方法級別的註釋,我能夠得到切入點和建議,我可以將註釋作爲參數傳遞,但我不知道如何爲類級註釋實現相同。

下面的代碼有效,但我需要在下面的程序中獲取註釋作爲參數「LogExecutionTimeByClass」的參數,我無法獲得相應的建議或切入點。

譯註:

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

看點:

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

/* 
    */ 
} 

註解類:

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

主要課程:

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

輸出:

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 

請注意,使用Spring不是一個選項。我必須使用AspectJ編譯器。 我編譯我的類並將它們打包爲jar,並使用ApsectJ編譯器使用下面的命令編織該方面。

AJC -inpath core.jar添加-outjar .. \ LIB \ core_woven.jar -1.5

任何指針將是有益的。

回答

12

該解決方案其實很簡單。我使用本地AspectJ風格編寫代碼,爲了清晰起見,我更喜歡它。您將能夠輕鬆地將其調整到@AspectJ註解風格:

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

輸出如下:

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

正如你所看到的,

  • 沒有必要around()意見,before()是足夠的,除非你想操縱任何參數或阻止捕獲的方法執行,你可以綁定的
  • 如果您只使用正確的語法,則可通過@annotation()@within()將有問題的註釋轉換爲命名參數。

享受!:-)


更新:這裏是爲您提供便利方面的@AspectJ版本,因爲你似乎有問題,從本地語法適應我的解決方案:

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

結果將是與我的原始版本相同。

+0

謝謝。讓我試試。 Around的原因是獲取該方法的執行時間。 – param83

+0

我嘗試過,但無法通過註釋參數通過內部但下面的切點工作@Pointcut(「publicMethod()&& beanAnnotatedWithMonitor()&& @annotation(annotation)」) – param83

+0

您真的不需要'beanAnnotatedWithMonitor()',請參閱我上面的更新。 – kriegaex