How to define dot abbreviations for a sequence of method (s)?

For example, if I have 3 classes,

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

      

Now I want to define a point abbreviation for the stream doB () -> doA (), for example if doB () calls doA (), grabs parameters from class A and class B and does something in the aspect. Can anyone help me.

+3


source to share


1 answer


Let me expand your example code a bit so that you understand what my solution does and what it cannot do:

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
    }
}

      

As you can see, there is now a new class C

and we now have three control flows:

  • MyClass.main -> A.doA

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

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



You want to eliminate # 1 and capture # 2, but what about # 3? In this case, it a.doA

is called indirectly from B.doB

through C.doC

. My solution also fixes this indirect case. If this is good for you, or if it doesn't happen in your codebase, you can use my solution. Otherwise, things will get a little more complicated and you will need to check the call stack. Tell me if you need to exclude # 2 and I'll continue with my answer, but the solution won't look as easy as this, I can promise.

Now here's the aspect:

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

      

The console output looks like this:

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

      

Note that we have the same object IDs B

on both outputs, but because it C.doC

creates a new object A

, we have two different object IDs A

.

+2


source







All Articles