AspectJ控制流/多个连接点

时间:2016-03-14 15:31:06

标签: java aspectj

我正在尝试学习AspectJ并弄清楚如何在流中的某些点检索特定的连接点。我的例子是这样的:

我想运行一个用JUnit的@Test注释的单元测试然后在该测试中调用的任何方法可能在另一个用另一个注释注释的类中,比方说@Example,然后我基本上可以访问这些特定点的整个流程因此我能够获得用@Test注释的测试的类名/方法名称,然后获取注释方法@Example的方法信息。我已经包含了一些示例代码以便澄清:

测试类:

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

POJO:

public class ExampleClass {
  @Example
  public void something() {
    // do something
  end
end

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

我试过这样的事情:

@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())。检索它的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

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

请注意,这不适用于execution()样式切入点,仅适用于call()样式切入点,否则JoinPoint.EnclosingStaticPartJoinPoint.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 q35991663.com.example.ExampleClass.something() was invoked from void q35991663.com.example.ExampleTest.shouldTestSomething()

我也改写了你的examplePointCut。切入点表达式@annotation(com.example.Example)意味着

  

主题的注释类型为com.example.Example

的任何连接点

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