我不确定我是否正确理解您想要实现的目标,因为您的描述有些不准确。例如,切入点不是“执行”的,应用程序方法或方面内的通知是。所以我不确定您是否只想记录每个方法调用(或者可能是方法执行,请参见下面的区别)或者可能需要某种元方面来计算方面建议被执行的次数。我在这里假设前一种更简单的情况,因为它对我来说最有意义。
您的应用程序代码,但带有包名称:
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(..) 的执行也会被记录,即使该方法从未被显式调用(但仍然执行!)。
切面拦截方法执行:
这方面会拦截您自己代码中的所有方法调用,其中还包括对第三方或 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() 并限制对您自己的包的调用,例如:
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);
}
}
使用execution() 记录第一个MyAspect 版本:
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[]))