Ответ 1
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 нельзя определить во время компиляции, а во время выполнения также принадлежит поток управления (поэтому он приводит к вечной рекурсии...)
хорошо, подумайте о потоке управления, как о стеке вызовов, тогда вы получите представление об его использовании;)