Подтвердить что ты не робот

Аспектно-ориентированное программирование - что такое "cflow"?

Я упомянул ссылку AspectJ здесь в ней говорится, что 'cflow'

cflow(Pointcut) - каждая точка соединения в управляющий поток каждой точки соединения P выбранный Pointcut, включая P Сам

Это не совсем понятно для меня, и мне было интересно, может ли кто-нибудь еще немного рассказать о значении cflow? Зачем использовать его?

Спасибо, действительно.

4b9b3361

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

хорошо, подумайте о потоке управления, как о стеке вызовов, тогда вы получите представление об его использовании;)