cflow поможет вам проконсультировать весь поток управления. Давайте попробуем пример, у меня есть 4 маленьких класса
public class A {
public static void methodA() {
B.methodB();
}
}
public class B {
public static void methodB() {
C.methodC();
int a = 1;
int b = 2;
System.out.println( a + b );
}
}
public class C {
public static void methodC() {
D.methodD();
}
}
public class D {
public static void methodD() {
}
}
мой аспект:
public aspect CFlow {
public pointcut flow() : cflow(call( * B.methodB() ) ) && !within(CFlow);
before() : flow() {
System.out.println( thisJoinPoint );
}
}
и мой бегун (просто чтобы посмотреть, что происходит):
public class Test {
public static void main(String[] args) {
A.methodA();
}
}
в моем pointcut вы могли видеть cflow(call( * B.methodB() ) )
, поэтому я хочу настроить управление аспектами, начиная с вызова B.methodB
, и когда вы запускаете тестовый класс, вы видите на консоли:
call(void test.B.methodB())
staticinitialization(test.B.<clinit>)
execution(void test.B.methodB())
call(void test.C.methodC())
staticinitialization(test.C.<clinit>)
execution(void test.C.methodC())
call(void test.D.methodD())
staticinitialization(test.D.<clinit>)
execution(void test.D.methodD())
get(PrintStream java.lang.System.out)
call(void java.io.PrintStream.println(int))
3
последняя строка не принадлежит аспекту, это просто из-за System.out.println
внутри methodB
. Все напечатанные показывают, что вы управляете потоком - цепочками методов и «событий» (выполнение, вызов, инициализация ...). Видите ли, я начал с класса Test
, который вызывал methodA
, но они не в «стеке», потому что нас интересовал methodB
поток управления.
Если вы хотите получить этот стек, но без первой строки (вызывающей себя), вы можете попытаться определить
public pointcut flow() : cflowbelow(call( * B.methodB() ) ) && !within(CFlow);
cflowbelow - еще один pointcut, который означает поток управления, исключая указанный (в нашем случае вызов B.methodB
).
Будьте осторожны, добавив !within(_aspect_)
в pointcut, иначе вы не получите ничего хорошего, кроме StackOverflowError
. Это происходит потому, что cflow не может быть определен во время компиляции, а во время выполнения аспект также относится к потоку управления (поэтому он ведет к вечной рекурсии ...)
хорошо, представьте, что поток управления похож на стек вызовов, тогда вы получите представление об его использовании;)