Java AspectJ控制流/多个连接点

Java AspectJ控制流/多个连接点,java,aspectj,Java,Aspectj,我试图学习AspectJ,并找出如何在流中的某些点检索特定的连接点。我的例子是这样的: @Aspect public class ExampleAspect { @Pointcut("execution(@org.junit.Test * *(..)) && !within(ExampleAspect)") public void testPointCut() {} @Pointcut("@annotation(com.example.E

我试图学习AspectJ,并找出如何在流中的某些点检索特定的连接点。我的例子是这样的:

@Aspect
public class ExampleAspect {
  @Pointcut("execution(@org.junit.Test * *(..)) 
             && !within(ExampleAspect)")
  public void testPointCut() {}

  @Pointcut("@annotation(com.example.Example)")
  public void examplePointCut() {}

  @After("cflow(testPointCut) && examplePointCut()")
  public void doSomething(JoinPoint joinPoint) {
    System.out.println(joinPoint.getSignature());
  }
}
void ExampleTest.ExampleClass.something()
我想运行一个用JUnit的
@test
注释的单元测试,然后在该测试中调用的任何方法可能位于另一个用另一个注释注释的类中,比如说
@Example
,然后我基本上可以访问这些特定点的整个流,这样我就可以获得用
@test
注释的测试的类名/方法名,然后还可以获得注释的
@Example
方法的方法信息。我已经包含了一些示例代码以供澄清:

测试等级:

public class ExampleTest {
  @Test
  public void shouldTestSomething() {
    ExampleClass exampleClazz = new ExampleClass();
    exampleClazz.something();
    // ...
  }
POJO:

因此,对于这些类,我想创建一个方面,基本上可以找到在
@Test
中调用的任何类型的
@Example
,这样我就可以访问两个(或更多)连接点,从AspectJ
连接点
对象中获取方法/类签名

我试过这样的方法:

@Aspect
public class ExampleAspect {
  @Pointcut("execution(@org.junit.Test * *(..)) 
             && !within(ExampleAspect)")
  public void testPointCut() {}

  @Pointcut("@annotation(com.example.Example)")
  public void examplePointCut() {}

  @After("cflow(testPointCut) && examplePointCut()")
  public void doSomething(JoinPoint joinPoint) {
    System.out.println(joinPoint.getSignature());
  }
}
void ExampleTest.ExampleClass.something()
但输出如下所示:

@Aspect
public class ExampleAspect {
  @Pointcut("execution(@org.junit.Test * *(..)) 
             && !within(ExampleAspect)")
  public void testPointCut() {}

  @Pointcut("@annotation(com.example.Example)")
  public void examplePointCut() {}

  @After("cflow(testPointCut) && examplePointCut()")
  public void doSomething(JoinPoint joinPoint) {
    System.out.println(joinPoint.getSignature());
  }
}
void ExampleTest.ExampleClass.something()

主要问题是签名中缺少测试方法的名称(shouldTestSomething())。检索它的最佳方法是什么?

不确定我是否理解正确,但是如果您需要访问有关调用您感兴趣的连接点下的一段代码的上下文的信息,那么您需要的是
thisEnclosingJoinPointStaticPart
(在本机AspectJ语法中)。如果您使用的是AspectJ 5注释样式特性,只需使用类型
JoinPoint.enclosuringStaticPart
向advice方法添加一个参数即可

请注意,这不适用于
execution()
style切入点,仅适用于
call()
style切入点,否则
JoinPoint.EnclosingStaticPart
JoinPoint.StaticPart
将是相同的

这意味着您需要按以下方式重写方面:

@Aspect
public class ExampleAspect {

    @Pointcut("execution(@org.junit.Test * *(..)) && !within(ExampleAspect)")
    public void testPointCut() {
    }

    @Pointcut("call(@com.example.Example * *(..))")
    public void examplePointCut() {
    }

    @After("cflow(testPointCut()) && examplePointCut()")
    public void doSomething(JoinPoint joinPoint, EnclosingStaticPart enclosingStaticPart) {
        System.out.println(joinPoint.getSignature() + " was invoked from "
            + enclosingStaticPart.getSignature());
    }

}
测试代码的输出为:

void q3599163.com.example.ExampleClass.something()是从void q3599163.com.example.ExampleTest.shouldTestSomething()调用的。

我还重写了你的
示例切入点
。切入点表达式
@annotation(com.example.example)
的意思是

主题具有类型为
com.example.example


这将包括
execution()
call()
类型连接点。在这种情况下,我们只需要
call()
连接点,因此如果您不打算将注释的值绑定到通知上下文,则甚至不需要
@annotation()

这非常有效!感谢您解释如何使用
call()
而不是
execution()