使用Aspectj调用joinPoint.getArgs时,如何忽略带有javax批注的参数? [英] How to ignore parameters with javax annotation when calling joinPoint.getArgs using Aspectj?

查看:1146
本文介绍了使用Aspectj调用joinPoint.getArgs时,如何忽略带有javax批注的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有包含不同javax Query批注的函数,例如:@QueryParam@Context@PathParam等.

I have functions that include different javax Query annotations like : @QueryParam , @Context , @PathParam etc..

在调用joinPoint.getArgs()时是否有排除这些参数的方法?

is there a way to exclude these parameters when calling 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%标记为持久.这意味着我希望将输入数据保存在某些持久性服务中.查询与上下文参数对我而言并不重要,但是输入数据本身很重要.

The reason I want to do it is that I have several urls, while marking ~10% as persistent. It means that I want the input data to be saved in some persistent service. The Query & Context params are not important to me, but the input data itself is.

推荐答案

假设您真的像许多其他人一样真正使用 full AspectJ而不是Spring AOP ,您应该意识到以下事实: @annotation(XY)不仅可能匹配execution()连接点,而且可能匹配call(),即您的建议将被触发两次.更糟糕的是,如果还注释了方法执行以外的其他地方-例如类,字段,构造函数,参数-切入点也将匹配,并且尝试转换为MethodSignature的尝试将因此导致异常.

Assuming you really use full AspectJ and not Spring AOP like so many others, you should be aware of the fact that in full AspectJ @annotation(XY) potentially matches not just execution() joinpoints but also call(), i.e. your advice will be triggered twice. Even worse, if other places than method executions are also annotated - e.g. classes, fields, constructors, parameters - the pointcut will also match and your try to cast to MethodSignature will cause an exception as a consequence.

此外,请注意,在@AspectJ语法中,您需要提供要与之匹配的注释的完全限定的类名,即不要忘记在包名前也加上它.否则,将根本没有匹配项.因此,在执行其他任何操作之前,您都希望将切入点更改为:

Furthermore, please note that in @AspectJ syntax you need to provide the fully qualified class name of the annotation you want to match against, i.e. don't forget to also prepend the package name. Otherwise there will be no match at all. So before doing anything else you want to change your pointcut to:

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

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

Now here is a fully self-consistent example, an SSCCE producing repeatable results, as requested by me in the comment under your question:

注释:

package de.scrum_master.app;

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

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

驱动程序应用程序:

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

As you can see, the test method has parameters with different types of annotations:

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

我们要忽略#1/2,而只打印#3/4.

We want to ignore #1/2 and only print #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 开始在其代码片段中显示的那样,您需要遍历参数和注释数组以实现过滤技巧.我认为这样做很丑陋,可能只是为了日志记录而变慢(我想这就是您想要做的事),但是出于它的价值,这是您的解决方案:

Just as user Andre Paschoal started to show in his code fragment, you need to iterate over both the arguments and annotations arrays in order to pull off the filtering trick. I think it is quite ugly and possibly slow just for logging's sake (and I assume this is what you want to do), but for what it is worth, here is your solution:

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

Tadaa! :-)

Tadaa! :-)

这篇关于使用Aspectj调用joinPoint.getArgs时,如何忽略带有javax批注的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆