使用Aspectj调用joinPoint.getArgs时如何忽略带有javax注释的参数?

2023-12-13

我有包含不同 javax 查询注释的函数,例如:@QueryParam , @Context , @PathParam etc..

有没有办法在调用 joinPoint.getArgs() 时排除这些参数?

Example:

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("{pathParam}/v1/{pathParam2}/")
    @MyAnnotation
    public Response update(@PathParam("pathParam") String p1, @PathParam("pathParam2") int p2, MyObject x);



    @Before("@annotation(MyAnnotation)")
        public void doSomething(JoinPoint joinPoint){
            Object[] objects = joinPoint.getArgs(); // HERE - is there a way to get only MyObject and not other params..?
    }

我想要这样做的原因是我有几个 url,同时将 ~10% 标记为持久。这意味着我希望将输入数据保存在某些持久服务中。查询和上下文参数对我来说并不重要,但输入数据本身很重要。


假设你真的使用完整的 AspectJ 而不是 Spring AOP像许多其他人一样,您应该意识到完整的 AspectJ@annotation(XY)潜在的匹配不仅仅是execution()连接点还call(),即您的建议将被触发两次。更糟糕的是,如果方法执行之外的其他地方也被注释 - 例如类、字段、构造函数、参数 - 切入点也将匹配并且您尝试强制转换为MethodSignature结果将导致异常。

此外,请注意,在 @AspectJ 语法中,您需要提供要匹配的注释的完全限定类名,即不要忘记在前面添加包名称。否则根本就没有比赛。因此,在执行其他操作之前,您需要将切入点更改为:

@annotation(de.scrum_master.app.MyAnnotation) && execution(* *(..))

现在这是一个完全自洽的例子,SSCCE按照我在您问题下的评论中的要求,产生可重复的结果:

注解:

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}

驱动程序应用:

正如您所看到的,测试方法具有带有不同类型注释的参数:

  1. 仅javax注释
  2. javax + 自己的注释
  3. 只有你自己的注释
  4. 无注释

我们想忽略 #1/2 并只打印 #3/4。

package de.scrum_master.app;

import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

public class Application {
  public static void main(String[] args) {
    new Application().update("foo", 11, "bar", 22);
  }

  @MyAnnotation
  public Response update(
    @PathParam("pathParam") String p1,
    @PathParam("pathParam2") @MyAnnotation int p2,
    @MyAnnotation String text,
    int number
  ) {
    return null;
  }
}

Aspect:

就像用户一样安德烈·帕绍尔开始在他的代码片段中显示,您需要迭代参数和注释数组才能实现过滤技巧。我认为它非常丑陋,并且可能只是为了记录而缓慢(并且我认为这就是您想要做的),但对于它的价值,这是您的解决方案:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class ParameterFilterAspect {
  @Before("@annotation(de.scrum_master.app.MyAnnotation) && execution(* *(..))")
  public void doSomething(JoinPoint joinPoint) {
    Object[] args = joinPoint.getArgs();
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
    for (int i = 0; i < args.length; i++) {
      boolean hasJavaxAnnotation = false;
      for (Annotation annotation : annotationMatrix[i]) {
        if (annotation.annotationType().getPackage().getName().startsWith("javax.")) {
          hasJavaxAnnotation = true;
          break;
        }
      }
      if (!hasJavaxAnnotation)
        System.out.println(args[i]);
    }
  }
}

控制台日志:

bar
22

哒哒! :-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Aspectj调用joinPoint.getArgs时如何忽略带有javax注释的参数? 的相关文章

随机推荐