簡體   English   中英

@AspectJ 類級別的注解建議,以注解作為方法參數

[英]@AspectJ Class level Annotation Advice with Annotation as method argument

如何讓注釋作為為類級注釋定義的 Advice 的參數傳遞? 是否有可能?

這里的帖子中我能夠獲得標識類中所有公共方法的切入點,這些方法由特定的注釋標記。 我也能夠得到應用的建議。 但是,我不知道如何在上述情況下獲取作為參數傳遞的注釋變量。

對於方法級注釋,我能夠獲得切入點和建議,在其中我可以將注釋作為參數傳遞,但我不知道如何為類級注釋實現相同的目標。

下面的代碼有效,但我需要在下面的程序中獲得注釋作為建議“ 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

任何指針都會有所幫助。

解決方法其實很簡單。 我正在以原生 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();
    }
}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM