1

我的函数包含不同的 javax 查询注释,如 : 、@QueryParam等。@Context@PathParam

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

例子:

    @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% 标记为持久性。这意味着我希望将输入数据保存在某个持久服务中。查询和上下文参数对我来说并不重要,但输入数据本身很重要。

4

3 回答 3

3

假设你真的使用完整的 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;
  }
}

方面:

正如用户Andre Paschoal开始在他的代码片段中展示的那样,您需要遍历参数和注释数组以完成过滤技巧。我认为这很丑陋,并且可能只是为了记录而很慢(我认为这是你想要做的),但为了它的价值,这是你的解决方案:

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

多多!:-)

于 2017-03-02T16:39:57.633 回答
0

我不认为有什么神奇的方法可以做到这一点,所以用显而易见的方法:

  • 定义你的论点接受标准;
  • 遍历 args 并根据先前定义的条件进行过滤,仅此而已。

看来您的接受标准是 arg 没有使用这些javax注释进行注释,对吗?

尝试这个:

Object[] args = joinPoint.getArgs();
Annotation[][] anns = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterAnnotations();

for (int i = 0; i < args.length; i++) {
    for (int j = 0; j < args[i].length; j++) {
        // check here for the annotations you would like to exclude
    }
}
于 2017-03-01T17:14:03.133 回答
0

这个片段代码对我有用:

Annotation[][] anns = ((MethodSignature)   thisJoinPoint.getSignature()).getMethod().getParameterAnnotations();

parameterValues = thisJoinPoint.getArgs();
signature = (MethodSignature) thisJoinPoint.getSignature();
parameterNames = signature.getParameterNames();
if (parameterValues != null) {
    for (int i = 0; i < parameterValues.length; i++) {

        boolean shouldBeExcluded = false;
        for (Annotation annotation : anns[i]) {
            if (annotation instanceof ExcludeFromCustomLogging) {//<<---------ExcludeFromCustomLogging is my class
                shouldBeExcluded = true;
                break;
            }
        }
        if (shouldBeExcluded) {
            //System.out.println("should be excluded===>"+parameterNames[i]);
            continue;
        }

  //.......and your business

}
于 2019-11-24T07:24:54.033 回答