【问题标题】:Get the name of a concrete class within aspectJ advice在 aspectJ 建议中获取具体类的名称
【发布时间】:2016-08-03 15:29:48
【问题描述】:

我正在尝试使用 aspectJ 来拦截对实现我的 Loggable 接口的类上的公共方法的调用。 Loggable 是一个标记接口,没有定义任何方法。

我有一个before 建议,我想在其中获取包含正在调用的方法的具体类的名称。通过使用thisJoinPoint.getTarget(),我可以获得具体的类,但是当我调用thisJoinPoint.getTarget().getClass.getName() 时,我得到了一个stackoverflow 异常。

我很确定这是因为我在 Concrete 类上调用了一个公共方法,这会导致我的 before 建议重新触发。

这是我的切入点:

pointcut dave() : target(Loggable) && call (public * *(..) ) ;

如何将其限制为直接在具体类中定义的公共方法,而忽略那些从 java.lang.Object 继承的方法?

【问题讨论】:

  • 这似乎可行:pointcut dave() : target(Loggable) && call (public * *(..) ) && !this(LoggerAspect); - 关于它是否是一个好方法的任何意见? ( Logger Aspect 是我的切面的名称,所以我基本上是说不要将切入点应用于源自切面本身的调用。)

标签: java aop aspectj


【解决方案1】:

虽然 StackOverflow 不是基于意见的讨论论坛,但我将用一些具体的例子来回答,以便更明确一点:

如果!this(LoggerAspect) 适合您,请使用它。但请注意:当 call() 是间接的,即您的通知调用的方法调用另一个方法时,它不会阻止通知触发。

选项 1:使用 execution() 而不是 call()

当使用execution() 切入点时,AspectJ 仅在被调用者被执行时触发,即在一个地方,而不是在调用者调用你的被调用者的许多地方。这更有效,并且在这种情况下对您有用,因为您似乎可以控制被调用的代码。只有当切面编织器/编译器确实可以访问被调用者时,您才应该使用call() 切入点编织调用者。

作为副作用,execution() 无论如何都不会拦截第 3 方库或 JDK 代码的执行,因为编译器/编织器无法访问它,一个例外是第 3 方库(但不是 JDK 代码)通过编织LTW(加载时编织)。

选项 2:adviceexecution() 切入点

通过将您的切入点与&& !adviceexecution() 结合使用,您可以在您的任何方面的任何建议正在执行时,在发出call() 时阻止建议触发。这也排除了间接调用,并且非常适合单个建议。但是,如果您结合多个方面并希望您的建议在另一个方面的建议发出 call() 时仍然触发,您可能希望使用其他选项,例如...

选项 3:within() 切入点

通过将您的切入点与&& !within(LoggerAspect) 结合使用,您可以在call() 从您的LoggerAspect 中的任何建议中生成call() 时阻止该建议触发。其他方面的电话仍在记录中。

您想要实现的具体目标决定了您应该选择哪个选项(或其组合)。没有简单的答案,因为我不知道你的具体情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2011-07-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多