在 aspectJ 建议中获取具体 class 的名称
Get the name of a concrete class within aspectJ advice
我正在尝试使用 aspectJ 来拦截对实现我的 Loggable
接口的 classes 上的 public 方法的调用。 Loggable 是一个标记接口,没有定义任何方法。
我有一个 before
建议,我想在其中获取包含正在调用的方法的 Concrete class 的名称。通过使用 thisJoinPoint.getTarget()
我可以获得具体的 class,但是当我调用 thisJoinPoint.getTarget().getClass.getName()
时我得到一个 Whosebug 异常。
我很确定这是因为我在 Concrete class 上调用了 public 方法,这导致我的 before
建议重新启动。
这是我的切入点:
pointcut dave() : target(Loggable) && call (public * *(..) ) ;
如何将其限制为 仅 直接在具体 class 中定义的 public 方法,忽略从 java.lang.Object?
虽然 Whosebug 不是一个基于意见的讨论论坛,但为了更明确一点,我将用一些具体的例子来回答:
如果 !this(LoggerAspect)
适合您,请使用它。但要注意:当 call()
是间接的,即你的建议调用的方法调用另一个方法时,它不会阻止建议触发。
选项 1:使用 execution()
而不是 call()
当使用 execution()
切入点时,AspectJ 仅在被调用者执行时触发,即在一个地方,而不是在调用者调用被调用者的许多地方。这样效率更高,并且在这种情况下对您有用,因为您似乎可以控制被调用的代码。仅当方面 weaver/compiler 确实可以访问被调用方时,您才应该使用 call()
切入点编织调用方。
作为副作用,第 3 方库或 JDK 代码的执行无论如何都不会被 execution()
拦截,因为 compiler/weaver 无法访问它,一个例外是第 3 个通过 LTW(加载时编织)编织的派对库(但不是 JDK 代码)。
选项 2:adviceexecution()
切入点
通过将你的切入点与 && !adviceexecution()
相结合,你可以在你的任何方面的任何建议正在执行时停止在 call()
时触发建议。这也排除了间接调用,并且可以很好地处理单个建议。但是如果你结合了多个方面并且希望你的建议在另一个方面的建议做出 call()
时仍然触发,你可能想要使用另一个选项,例如...
选项 3:within()
切入点
通过将切入点与 && !within(LoggerAspect)
组合,当 LoggerAspect
中的任何建议中出现 call()
时,您可以停止触发建议。来自其他方面的呼叫仍在记录中。
您想要实现的目标决定了您应该选择哪个选项(或其组合)。没有简单的答案,因为我不知道你的具体情况。
我正在尝试使用 aspectJ 来拦截对实现我的 Loggable
接口的 classes 上的 public 方法的调用。 Loggable 是一个标记接口,没有定义任何方法。
我有一个 before
建议,我想在其中获取包含正在调用的方法的 Concrete class 的名称。通过使用 thisJoinPoint.getTarget()
我可以获得具体的 class,但是当我调用 thisJoinPoint.getTarget().getClass.getName()
时我得到一个 Whosebug 异常。
我很确定这是因为我在 Concrete class 上调用了 public 方法,这导致我的 before
建议重新启动。
这是我的切入点:
pointcut dave() : target(Loggable) && call (public * *(..) ) ;
如何将其限制为 仅 直接在具体 class 中定义的 public 方法,忽略从 java.lang.Object?
虽然 Whosebug 不是一个基于意见的讨论论坛,但为了更明确一点,我将用一些具体的例子来回答:
如果 !this(LoggerAspect)
适合您,请使用它。但要注意:当 call()
是间接的,即你的建议调用的方法调用另一个方法时,它不会阻止建议触发。
选项 1:使用 execution()
而不是 call()
当使用 execution()
切入点时,AspectJ 仅在被调用者执行时触发,即在一个地方,而不是在调用者调用被调用者的许多地方。这样效率更高,并且在这种情况下对您有用,因为您似乎可以控制被调用的代码。仅当方面 weaver/compiler 确实可以访问被调用方时,您才应该使用 call()
切入点编织调用方。
作为副作用,第 3 方库或 JDK 代码的执行无论如何都不会被 execution()
拦截,因为 compiler/weaver 无法访问它,一个例外是第 3 个通过 LTW(加载时编织)编织的派对库(但不是 JDK 代码)。
选项 2:adviceexecution()
切入点
通过将你的切入点与 && !adviceexecution()
相结合,你可以在你的任何方面的任何建议正在执行时停止在 call()
时触发建议。这也排除了间接调用,并且可以很好地处理单个建议。但是如果你结合了多个方面并且希望你的建议在另一个方面的建议做出 call()
时仍然触发,你可能想要使用另一个选项,例如...
选项 3:within()
切入点
通过将切入点与 && !within(LoggerAspect)
组合,当 LoggerAspect
中的任何建议中出现 call()
时,您可以停止触发建议。来自其他方面的呼叫仍在记录中。
您想要实现的目标决定了您应该选择哪个选项(或其组合)。没有简单的答案,因为我不知道你的具体情况。