如何为一系列方法定义点切割?

时间:2014-12-09 08:45:43

标签: aop aspectj spring-aop

例如,如果我有3个班级,

class A {
    public void doA() {
        /* do something */
    }
}

class B {
    public void doB() {
        A a = new A();
        a.doA();
    }
}

class MyClass {
    public static void main(String args[]) {
        B b = new B();
        b.doB();
    }
}

现在我想为流程doB()定义一个切点 - > doA(),就像doB()调用doA()从类A和类B中获取参数并在aspect方法中执行某些操作一样。有人可以帮助我。

1 个答案:

答案 0 :(得分:2)

让我稍微扩展您的示例代码,以便让您了解我的解决方案做了什么以及它不能做什么:

class A {
    public void doA() {}
}
class B {
    public void doB() {
        new A().doA();
        new C().doC();
    }
}
class C {
    public void doC() {
        new A().doA();
    }
}
class MyClass {
    public static void main(String args[]) {
        new A().doA();      // should not be captured
        new B().doB();      // should be captured
    }
}

如您所见,现在有一个新类C,我们现在有三个控制流程:

  • MyClass.main -> A.doA
  • MyClass.main -> B.doB -> A.doA
  • MyClass.main -> B.doB -> C.doC -> A.doA

你想要排除#1并捕获#2,但是#3呢?在这种情况下,a.doAB.doB通过C.doC被称为间接。我的解决方案也捕获了这种间接情况。如果这对您来说没问题,或者在您的代码库中没有发生,您可以使用我的解决方案。否则事情会变得复杂一些,你需要检查调用堆栈。告诉我你是否需要排除#2,我会扩展我的答案,但解决方案看起来不会像这个那么简单,我可以保证。

现在是方面:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class ControlFlowInterceptor {
    @Before("execution(void A.doA()) && target(a) && cflow(execution(void B.doB()) && target(b))")
    public void advice(JoinPoint thisJoinPoint, A a, B b) {
        System.out.println(thisJoinPoint);
        System.out.println("  " + a);
        System.out.println("  " + b);
    }
}

控制台输出如下所示:

execution(void A.doA())
  A@7b19f779
  B@65c66812
execution(void A.doA())
  A@4df2868
  B@65c66812

请注意,我们在两个输出中都有相同的B对象ID,但由于C.doC创建了一个新的A对象,因此我们有两个不同的A对象ID。