2013-07-05 71 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