Аспект, чтобы найти все pointcut, выполненные во время выполнения - PullRequest
0 голосов
/ 22 января 2019

Мне нужно написать аспект (назовем его A), который показывает все выполненные pointcut во время выполнения. Есть ли способ написать pointcut, такой как call (...), который указывает непосредственно на другой pointcut без использования имен аспектов?

Я написал что-то, что использует в основном вызовы универсальных функций и в пределах (), чтобы при вызове функции в аспекте мой аспект А печатал что-то. Я чувствую, что это не идеальное решение, потому что мне всегда нужно было бы писать имена всех аспектов, и было бы долго со многими аспектами.

public class Main {
    public static void main(String[] args) {
        ClassA a = new ClassA();
        a.methodA();
        a.methodA();
        a.methodB();
        a.methodA();
    }
}

public class ClassA {
    public void methodA() {
            System.out.println("MethodA");
    }
    public void methodB() {
        System.out.println("MethodB");
    }
    public void methodC() {
        System.out.println("MethodC");
    }
}

public aspect MethodAAspect {
    pointcut MethA():
        call(public * ClassA.methodA());
    pointcut MethC():
        call(public * ClassA.methodC());
    after():
        MethA() {
            System.out.println("Aspect here, methodA ended.");
        }
    after():
        MethC() {
            System.out.println("Aspect here, methodC ended.");
        }       
}

Если в этом примере мне понадобится аспект, который подсчитывает, сколько раз были выполнены все pointcut, или печатает что-либо при выполнении pointcut, как мне написать это?

1 Ответ

0 голосов
/ 03 февраля 2019

Я не уверен, что правильно понимаю, чего вы хотите достичь, потому что ваше описание несколько неточно.Например, pointcut не «выполняется», метод приложения или совет внутри аспекта.Так что я не уверен, хотите ли вы просто регистрировать каждый вызов метода (или, возможно, выполнение метода, смотрите разницу ниже) или, возможно, нужен какой-то мета аспект, который подсчитывает, сколько раз выполняются советы по аспектам.Я предполагаю, что первый, более простой случай здесь, потому что он имеет наибольшее значение для меня.

Код вашего приложения, но с именами пакетов:

package de.scrum_master.app;

public class ClassA {
  public void methodA() {
    System.out.println("MethodA");
  }

  public void methodB() {
    System.out.println("MethodB");
  }

  public void methodC() {
    System.out.println("MethodC");
  }
}
package de.scrum_master.app;

public class Main {
  public static void main(String[] args) {
    ClassA a = new ClassA();
    a.methodA();
    a.methodA();
    a.methodB();
    a.methodA();
  }
}

Аспект перехвата выполнения метода:

Этот аспект перехватывает все методы выполнения (не вызовы!) В вашем собственном коде.

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : execution(* *(..)) {
    System.out.println(thisJoinPoint);
  }
}

Журналвывод:

MethodA
execution(void de.scrum_master.app.ClassA.methodA())
MethodA
execution(void de.scrum_master.app.ClassA.methodA())
MethodB
execution(void de.scrum_master.app.ClassA.methodB())
MethodA
execution(void de.scrum_master.app.ClassA.methodA())
execution(void de.scrum_master.app.Main.main(String[]))

Обратите внимание, что также регистрируется выполнение Main.main(..), даже если метод никогда не вызывается явно (но, тем не менее, выполняется!).

Aspectперехват выполнения метода:

Этот аспект перехватывает все методы вызовы из вашего собственного кода, который также включает в себя вызовы сторонним классам или классам JDK.

Обратите вниманиечто, чтобы избежать бесконечного цикла, мы должны добавить && !within(MyAspect), потому что совет аспекта также вызывает метод JDK.

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : call(* *(..)) && !within(MyAspect) {
    System.out.println(thisJoinPoint);
  }
}

В этом случае вывод журнала:

MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())
MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())
MethodB
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodB())
MethodA
call(void java.io.PrintStream.println(String))
call(void de.scrum_master.app.ClassA.methodA())

Конечно, вы также можете использовать call() и ограничить количество звонков на свой телефон.ckages, например:

package de.scrum_master.aspect;

public aspect MyAspect {
  after() : call(* de.scrum_master.app..*(..)) && !within(MyAspect) {
    System.out.println(thisJoinPoint);
  }
}

Вывод журнала здесь:

MethodA
call(void de.scrum_master.app.ClassA.methodA())
MethodA
call(void de.scrum_master.app.ClassA.methodA())
MethodB
call(void de.scrum_master.app.ClassA.methodB())
MethodA
call(void de.scrum_master.app.ClassA.methodA())

Это всегда зависит от того, чего вы хотите достичь.

Если это не то, чтоВы хотели, пожалуйста, обновите свой вопрос, чтобы быть более точным и сообщите мне с комментарием.Затем я вижу, что я могу сделать.


Обновление, касающееся дополнительного вопроса о мета-аспекте:

package de.scrum_master.aspect;

public aspect MetaAspect {
  before() : adviceexecution() && !within(MetaAspect) {
    System.out.println(thisJoinPoint);
  }
}

Журнал для первой MyAspect версии с использованиемexecution() изменяется на:

MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
MethodB
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodB())
MethodA
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.ClassA.methodA())
adviceexecution(void de.scrum_master.aspect.MyAspect.after(JoinPoint))
execution(void de.scrum_master.app.Main.main(String[]))
...