gpt4 book ai didi

java - @AspectJ 以注解作为方法参数的类级注解建议

转载 作者:搜寻专家 更新时间:2023-10-31 08:17:14 24 4
gpt4 key购买 nike

我怎样才能让注释作为参数传递给定义为类级别注释?可能吗?

来自帖子 here我能够获得标识类中由特定注释标记的所有公共(public)方法的切点。我也能够得到应用的建议。但是,在上述情况下,我不知道如何将注释变量作为参数传递。

对于方法级注释,我能够获得切入点和建议,我可以在其中将注释作为参数传递,但我不知道如何为类级注释实现相同的功能。

下面的代码有效,但我需要在下面的程序中获取注释作为建议“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

任何指针都会有所帮助。

最佳答案

解决方法其实很简单。我正在以 native 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() 将相关注释绑定(bind)到命名参数。

尽情享受吧! :-)


更新:这是方面的@AspectJ 版本,为了您的方便,因为您似乎在从 native 语法改编我的解决方案时遇到问题:

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

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

关于java - @AspectJ 以注解作为方法参数的类级注解建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17481183/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com