以注释作为方法参数的@AspectJ类级别注释建议 [英] @AspectJ Class level Annotation Advice with Annotation as method argument

查看:82
本文介绍了以注释作为方法参数的@AspectJ类级别注释建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取注释作为为以下对象定义的建议"的参数传递 类级注释?有可能吗?

How can I get the annotation to be passed as the argument for the Advice defined for class-level annotation? Is it possible?

摘自此处我能够获得切入点,该切入点标识类中所有由特定批注标记的公共方法.我也能够得到建议的应用.但是,在上述情况下,我不知道如何将注释变量作为参数传递.

From the post here I am able to get the point cut that identifies all the public method in the class which is marked by a specific Annotation. I am able to get the advice applied as well. However, I don’t know how to get the annotation variable passed as argument in above case.

对于方法级别的注释,我可以获取切入点和建议,可以在其中获取作为参数传递的注释,但是我不知道如何为类级别的注释实现相同的目的.

For a method-level annotation, I am able to get the pointcut and advice in which I can get the annotation passed as argument, but I don’t know how to achieve the same for class-level annotation.

下面的代码可以工作,但是我需要在下面的程序中将注释作为建议" LogExecutionTimeByClass "的参数,而我无法为此获得适当的建议或切入点.

The below code works, but I need to get the annotation as the argument for the advice "LogExecutionTimeByClass" in below program and I couldn’t able to get appropriate advice or pointcut for the same.

注释:

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编译器使用以下命令来编织方面.

Please note that using Spring is is not an option. I have to use AspectJ compiler. I compiled my classes and packaged them as jar and use ApsectJ compiler to woven the aspect using below command.

ajc -inpath core.jar -outjar .. \ lib \ core_woven.jar -1.5

ajc -inpath core.jar -outjar ..\lib\core_woven.jar -1.5

任何指针都会有所帮助.

Any pointer would be helpful.

推荐答案

解决方案实际上非常简单.我正在以本机AspectJ风格编写代码,为清晰起见,我更喜欢它.您将可以轻松将其调整为@AspectJ批注样式:

The solution is actually quite simple. I am writing my code in native AspectJ style, I prefer it for clarity. You will be easily able to adjust it to @AspectJ annotation style:

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()将有问题的注释绑定到命名参数.
  • there is no need for around() advice, before() is sufficient unless you want to manipulate any parameters or block the captured method executions,
  • you can bind the annotations in question via @annotation() or @within() to named parameters if you just use the correct syntax.

享受! :-)

更新:为方便起见,这是该方面的@AspectJ版本,因为您似乎在适应本机语法与本机语法方面遇到问题:

Update: Here is the @AspectJ version of the aspect for your convenience and because you seemed to have problems adapting my solution from the native syntax:

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

结果将与我的原始版本相同.

The results will be identical to my original version.

这篇关于以注释作为方法参数的@AspectJ类级别注释建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆