在Spring Boot AOP中,如何在方法"Around"期间获取class注解?

In Spring Boot AOP, how to get class annotation when in the method "Around" period?

在此感谢所有的朋友。我知道如何获取 method.

上的注释集的注释参数

虽然我想在 Class 级别添加注释。如何在 AOP Around 方法中从 Class 中检索属性?

对了,我还有一个问题,为什么我需要将响应值从void更改为Object和return pjp.proceed()。如果方法没有响应,请求将冻结。

对于有HasRole注解的方法

@Around("@annotation(com.example.demo.aspect.annotation.HasRole) && @annotation(annotation)")
public void aroundHasRole(ProceedingJoinPoint pjp, HasRole annotation) throws Throwable {

    log.info("value->>{}", annotation.value());
    pjp.proceed();

}

对于 Class 或具有 HasRole 注释的方法

@Around("(@within(com.example.demo.aspect.annotation.IsAdmin)"
        + "|| @annotation(com.example.demo.aspect.annotation.IsAdmin))")
public Object aroundHasRole(ProceedingJoinPoint pjp) throws Throwable {

    <<How to get annotation information here?>>
    return pjp.proceed();

}

通过反射获取class,通过class获取固定的方法信息,获取方法上的注解。这样,你应该可以反映

您可能已经注意到,您不能将来自不同 || 分支的信息绑定到建议方法参数,因为这会产生歧义,另请参阅我的回答 and here。因此,如果您想避免丑陋(和缓慢)的反射,请按照我在其他答案中的建议进行操作并编写两个不同的建议,如果您在这里担心避免代码重复,则将通用代码分解为辅助方法。类似这样的东西(未经测试,只是为了让您了解代码结构):

@Around("@within(annotation)")
public Object classIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

@Around("@annotation(annotation)")
public Object methodIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  return commonIsAdmin(pjp, annotation);
}

public Object commonIsAdmin(ProceedingJoinPoint pjp, IsAdmin annotation) throws Throwable {
  // Here you would place all common advice code.
  // Non-common code could remain in the original advice methods.
  log.info("value->>{}", annotation.value());
  return pjp.proceed();
}

why I need to change the response value from void to Object and return pjp.proceed(). If the method do not have response, the request will freezing.

@Before@After 建议相反,在 @Around 建议中,您可以通过完全跳过目标方法执行来修改 return 值调用 proceed() 或丢弃或修改 proceed() 的结果。您完全可以自由选择 return,它只需要匹配目标方法的 return 类型即可。

话虽如此,但应该清楚的是,环绕通知方法还必须具有与它拦截的目标方法相匹配的 return 类型。它可以是一个精确的类型,如 MyType,一个超类型或简单的 Object(所有类型的超类型),如果你的建议针对多种类型而没有一个通用的超类型。如果(且仅当)所有目标方法也 return void 时,建议也可以具有 return 类型的 void (否则建议不会匹配这些方法,即使如果这样的切入点匹配)。

因此,是否匹配周围建议由切入点本身和 return 类型的组合决定。您可以将其用作通过定义特定 return 类型来限制切入点匹配的工具(然后您需要将 proceed() 的 return 值转换为该类型,因为 proceed() 总是return 一个 Object).

顺便说一句,如果目标方法 return 是原始类型,如 intboolean 等,那么建议 auto-wrap 结果将是 IntegerBoolean.

您真的应该阅读 Spring AOP 和 AspectJ 手册或教程,因为我在这里解释的内容可以在那里找到。


更新: OP 要求提供有关参数绑定的文档以及如何确定名称的说明:

  • 您可以为所有建议类型指定一个 argNames 参数,例如@Before, @After, @Around.
  • 如果该注释参数不存在,Spring AOP 将尝试通过 class 文件调试信息匹配建议方法参数名称,如果已编译。否则在这种情况下匹配将失败。
  • 当使用带有 compile-time 编织而不是 Spring AOP 的完整 AspectJ 时,确定名称也可以在没有调试信息的情况下工作,因为 AspectJ 编译器可以在编译期间确定必要的信息。

所有这些都在 Spring AOP manual 中描述。