简体   繁体   English

Spring Boot AOP中,在方法“Around”期间如何获取类注解?

[英]In Spring Boot AOP, how to get class annotation when in the method “Around” period?

Thanks for all the friends here.感谢这里的所有朋友。 I know how to get the annotation parameter for the annotation set on method .我知道如何获取method设置的注释的注释参数。

While I would like to add the annotation in the Class level.虽然我想在Class级别添加注释。 How to retrieve the attribute from Class in the AOP Around method?如何在 AOP Around 方法中从Class中检索属性?

By the way, I have another question, why I need to change the response value from void to Object and return pjp.proceed() .顺便说一句,我还有一个问题,为什么我需要将响应值从void更改为Object并返回pjp.proceed() If the method do not have response, the request will freezing.如果该方法没有响应,则请求将冻结。

For the Method which has HasRole annotation对于具有 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();

}

For Class or Method which has HasRole annotation对于具有 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();

}

As you probably have noticed, you cannot bind information from different ||您可能已经注意到,您不能绑定来自不同||信息。 branches to an advice method parameter because it would be ambiguous, see also my answers here and here .分支到建议方法参数,因为它会模棱两可,另请参阅我的答案herehere So if you want to avoid ugly (and slow) reflection, do what I recommended in the other answers and write two distinct advices, factoring out the common code into a helper method if avoiding code duplication is your concern here.因此,如果您想避免丑陋(和缓慢)的反射,请按照我在其他答案中的建议并编写两个不同的建议,如果您在这里担心避免代码重复,则将公共代码分解为辅助方法。 Something like this (untested, just to give you an idea about the code structure):像这样的东西(未经测试,只是为了让您了解代码结构):

@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() .为什么我需要将响应值从void更改为Object并返回pjp.proceed() If the method do not have response, the request will freezing.如果该方法没有响应,则请求将冻结。

In contrast to a @Before or @After advice, in an @Around advice you can modify the return value by either skipping the target method execution completely by not calling proceed() or by discarding or modifying the result of proceed() .在对比一个@Before@After建议,在一个@Around建议可以修改返回值通过或是不调用完全跳过目标方法的执行proceed()或通过丢弃或修改的结果proceed() You are completely free in what you want to return, it just has to match the target method's return type.您可以完全自由地选择要返回的内容,只需匹配目标方法的返回类型即可。

Having said that, it should become clear that an around advice method also must have a return type matching that of the target method(s) it intercepts.话虽如此,应该清楚的是,环绕通知方法还必须具有与其拦截的目标方法匹配的返回类型。 It can be an exact type like MyType , a super type or simply Object (super type for all types) if your advice targets a multitude of types without a common super type.如果您的建议针对多种类型而没有共同的超类型,则它可以是像MyType这样的精确类型、超类型或简单的Object (所有类型的超类型)。 The advice can also have a return type of void if (and only if) all target methods also return void (otherwise the advice just would not match those methods, even if the pointcut as such would match).当(且仅当)所有目标方法也返回void ,通知也可以具有void返回类型(否则通知将不匹配这些方法,即使切入点本身匹配)。

So if an around advice matches is determined by a combination of the pointcut itself and the return type.所以如果一个around通知匹配是由切入点本身和返回类型的组合决定的。 You can use that as a tool to limit pointcut matching by defining a specific return type (to which you then would need to cast the return value of proceed() because proceed() always returns an Object ).您可以将其用作通过定义特定返回类型来限制切入点匹配的工具(然后您需要将proceed()的返回值强制转换为该类型,因为proceed()总是返回一个Object )。

BTW, if the target method returns a primitive type like int , boolean etc., then the advice would auto-wrap the result to be an Integer or Boolean .顺便说一句,如果目标方法返回一个原始类型,如intboolean等,那么建议将自动包装结果为IntegerBoolean

You really ought to read Spring AOP and AspectJ manuals or tutorials because I am explaining things here which can be found there.您真的应该阅读 Spring AOP 和 AspectJ 手册或教程,因为我在这里解释了可以在那里找到的内容。


Update: The OP asked for documentation concerning parameter binding and a description how names are determined:更新: OP 要求提供有关参数绑定的文档以及如何确定名称的说明:

  • You can specify an argNames parameter for all advice types, eg @Before , @After , @Around .您可以指定一个argNames所有意见类型,例如参数@Before@After@Around
  • If that annotation parameter is absent, Spring AOP will try to match advice method parameter names via class file debug info, if compiled in. Otherwise matching would fail in this case.如果该注解参数不存在,Spring AOP 将尝试通过类文件调试信息匹配通知方法参数名称(如果已编译)。否则在这种情况下匹配将失败。
  • When using full AspectJ with compile-time weaving instead of Spring AOP, determining names also works without debug info because the AspectJ compiler can determine the necessary information during compilation.当使用带有编译时编织的完整 AspectJ 而不是 Spring AOP 时,确定名称也可以在没有调试信息的情况下工作,因为 AspectJ 编译器可以在编译期间确定必要的信息。

All of this is described in the Spring AOP manual .所有这些都在Spring AOP 手册中进行了描述。

Obtain the class through reflection, obtain the fixed method information through the class, and get the annotation on the method.通过反射获取类,通过类获取固定的方法信息,获取方法上的注解。 In this way, you should be able to reflect这样,你应该能够反映

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM