当前位置: 首页 > 知识库问答 >
问题:

如何为Spring AOP编写PointCut表达式以在任何深度级别编织元注释?

姬慎之
2023-03-14

如果我有注释:

@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Loggable {
  enum LogLevel {
    ERROR, WARN, INFO, DEBUG, TRACE;
  }

  LogLevel value() default DEBUG;
}

并尝试将其用作Spring AOP方面连接点标记的目标标记,它适用于某些方面,由该复合切入点编织:

@Aspect
class LoggableAspect {
  @Pointcut("within(@Loggable *)")
  void aClass() {}

  //@Pointcut("@annotation(Loggable)") - in straight-forward case it works too!
  @Pointcut("execution(@Loggable * *(..))")
  void method() {}

  @Around("method() || aClass()")
  Object aroundAdvice(ProceedingJoinPoint pjp) {...}
}

换句话说,当我编写这样的代码时,它与“直接”注释用法一样有效:

@Component
public class Abc {

  @Loggable
  public String method(int x) {
    return "string: " + x;
  }
}

但在元注释的情况下…:

java prettyprint-override">@Loggable(INFO)
@Retention(RUNTIME)
public @interface Log {
}

...例如,在该代码中,它不起作用:

@Component
public class Abc {

  @Log // doesn't work! :(
  public String method(int x) {
    return "string: " + x;
  }
}

当然,我可以为2级深度的特殊情况写另一个切入点:

//...

@Pointcut("execution(@(@Loggable *) * *(..))")
void metaMethod() {}

@Around("method() || metaMethod() || aClass()")
Object aroundAdvice(ProceedingJoinPoint pjp) {...}

它会起作用的,但我想要普遍的解决方案,在任何深度上工作-3,4,5。。。这种风格的AOP可能吗?

附言该问题:

execution(public * ((@Transactional *)+).*(..))

看起来是完全正确的解决方案,但不幸的是,它在我的情况下不起作用。我认为,它只可能作为AspectJ解决方案(在*.aj文件中)出现,而不适用于Spring AOP。我说得对吗?。。

共有1个答案

韩喜
2023-03-14

尽管您可能不喜欢,但对您的问题的正确答案是:Spring AOP作为AeyJ的语法子集和本机AeyJ都没有提供专用语法来实现您想要做的事情。您实际上能做的最好的事情就是像您自己建议的那样使用嵌套语法并使用合理数量的嵌套级别。

在我的回答中,您可以找到类级和方法级元注释的解决方案。

更新:你误解了什么

execution(public * ((@Transactional *)+).*(..))

意思是,即使你链接的答案解释了它:

匹配具有事务性注释的类型中任何公共方法的执行,或具有事务性注释的类型的任何子类型。

所以这个语法是关于类继承的,而不是关于元注释嵌套的。这意味着,如果你有@transnational class Parent,它将匹配class Child extensed Parentclass孙子extensed Child等。语法在Spring AOP中也应该起作用,但这并不能解决你的问题。

 类似资料:
  • 本文向大家介绍如何编写JSP表达式?,包括了如何编写JSP表达式?的使用技巧和注意事项,需要的朋友参考一下 JSP表达式元素包含一种脚本语言表达式,该脚本语言表达式经过评估,转换为String,并插入该表达式出现在JSP文件中的位置。 由于表达式的值已转换为字符串,因此可以在JSP文件的一行文本中使用表达式,无论是否用HTML标记。 expression元素可以包含根据Java语言规范有效的任何表

  • 我在用VB。net项目。我是VB新手。Net LINQ,并想知道Lambda的等效值 在VB中。网 有人请建议!

  • 我需要开发一个web服务,这将帮助客户机做一些周期性的工作,api将喜欢这个void Dojob(int jobType,string cronExpression);

  • 我想为上面的内容编写单元测试,以测试我正在使用的注释的sampleURL,比如如果我给出任何应该与regex模式匹配的URL。我浏览了以下链接:如何在spring中进行单元测试验证注释,如何使用JUnit测试类的验证注释?但它们没有多大帮助,我也有setSampleURL函数。那么,如何为sampleURL变量编写测试呢。基本上,我想为regex模式编写测试,即我给sampleURL的值是否与re

  • 我在Java 1.8中有以下代码。 如果没有lambda,如何将其转换为Java 1.7代码?

  • 本文向大家介绍如何仅使用C#为数字编写正则表达式?,包括了如何仅使用C#为数字编写正则表达式?的使用技巧和注意事项,需要的朋友参考一下 正则表达式是可以与输入文本匹配的模式。 .Net框架提供了允许此类匹配的正则表达式引擎。 模式由一个或多个字符文字,运算符或构造组成。 这是RegEx使用的基本模式元字符- ^符号用于指定非条件。 如果要给出范围值(例如0-9或az或AZ),请使用[]括号 示例