java @AspectJ 类级别的注释建议,以注释作为方法参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17481183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@AspectJ Class level Annotation Advice with Annotation as method argument
提问by param83
How can I get the annotation to be passed as the argument for the Advice defined for class-level annotation? Is it possible?
如何让注释作为为类级注释定义的 Advice 的参数传递?是否可以?
From the post hereI 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.
对于方法级别的注释,我可以获得切入点和建议,我可以在其中获取作为参数传递的注释,但我不知道如何为类级别的注释实现相同的目标。
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.
下面的代码有效,但我需要在下面的程序中获得注释作为建议“ LogExecutionTimeByClass”的参数,但我无法获得适当的建议或切入点。
Annotation:
注解:
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();
}
Aspect:
方面:
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();
}
/*
*/
}
Annotated Class:
注释类:
@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);
}
}
Main Program:
主程序:
public class AspectJMain {
public static void main(String[] args) throws InterruptedException {
Operator op = new Operator();
op.operate();
op.operate1();
}
}
Output:
输出:
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
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.
请注意,使用 Spring 不是一种选择。我必须使用 AspectJ 编译器。我编译了我的类并将它们打包为 jar 并使用 ApsectJ 编译器使用以下命令编织方面。
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.
任何指针都会有所帮助。
回答by kriegaex
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:
解决方法其实很简单。我正在以原生 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());
}
}
The output is as follows:
输出如下:
execution(void Operator.operate()) -> Method_Level_Invocation
execution(void Operator.operate()) -> Class_Level_Invocation
execution(void Operator.operate1()) -> Class_Level_Invocation
As you can see,
如你看到的,
- 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.
- 不需要
around()
建议,before()
除非您想操作任何参数或阻止捕获的方法执行,否则就足够了, - 如果您只使用正确的语法,您可以通过
@annotation()
或@within()
将有问题的注释绑定到命名参数。
Enjoy! :-)
享受! :-)
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:
更新:为了您的方便,这是方面的@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();
}
}
The results will be identical to my original version.
结果将与我的原始版本相同。