AspectJ,将本机库调用与应用程序调用分开

时间:2014-05-21 19:06:35

标签: aspectj

我正在使用AspectJ和Load-time编织来跟踪任意java程序中的方法调用。我可以使用标准跟踪所有呼叫:

call(* *.*(..))

但我现在要做的是分离对本机java库和任何应用程序代码的调用:

nativeCalls(): !within(MethodTracer) && call(* java..*.*(..));

appCalls(): !within(MethodTracer) && call(* *.*(..)) && !call(* java..*.*(..));

问题是nativeCalls()切入点正在挑选对从本机java类继承的应用程序类的调用,即使签名不是以java.lang开头的。或java.util等。

例如:

如果我有一个继承自java.awt.Component的类tetris.GameComponent,我的nativeCalls()切入点将在java.awt.Component.getBackground中实际实现该方法时选择tetris.GameComponent.getBackground() )。

有没有办法让我的nativeCalls()切入点忽略对继承方法的调用?

我希望这很清楚。如有必要,我可以提供其他信息。感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:1)

实际上我不知道为什么要从跟踪中排除那些继承的方法调用,因为IMO重要或者至少有趣的是知道是否在一个类上调用了一个方法,即使该方法是在一个类中定义的JDK超类。

但无论如何,答案是否定的,如果这些调用实际上是在对应用于某个应用程序类的目标对象上进行的,那么就不能从nativeCalls()切入点排除对JDK方法的调用。在调用时,AspectJ不知道JVM将如何解析多态性。可能有几种情况:

  • 致电Foo.aaa(),执行现有方法Foo.aaa()。这是一个实际存在被调用方法的简单情况。
  • 调用Foo.bbb(),执行继承的方法Base.bbb()(多态)。这是您要排除的情况,但您不能,因为只有在执行方法时才会知道调用基本方法的事实。此外,如果Base是JDK类,则甚至无法使用AspectJ拦截其方法执行。
  • 调用Base.ccc(),执行非重写方法Base.ccc()。如果您直接创建Base的实例,或者如果您将Foo实例分配/转换为类型为Base的变量,则可能会发生这种情况。 Base obj = new Foo(),并致电obj.ccc(),其中已被Foo覆盖。
  • 调用Base.ddd(),执行重写方法Foo.ddd()(polmorphism)。如果您将Foo实例分配/转换为变量类型Base,例如,也会发生这种情况。 Base obj = new Foo(),并致电已被obj.ddd()覆盖的Foo

在调用继承的JDK方法时,无法轻易排除多态性。

现在反过来说:您可以轻松地在应用程序类上拦截execution()而不是call(),并利用JDK方法执行无论如何都无法截获的事实:pointcut appMethod() : execution(* *(..)); < / p>