【问题标题】:Spring AOP pointcut for annotated argument注释参数的 Spring AOP 切入点
【发布时间】:2012-04-20 13:22:10
【问题描述】:

假设我有这样的方法:

public void method(@CustomAnnotation("value") String argument)

是否有一个切入点表达式可以选择所有带有@CustomAnnotation 注释的参数的方法?如果是这样,有没有办法让我访问“价值”参数?

【问题讨论】:

    标签: spring aop spring-aop pointcut


    【解决方案1】:

    关于选择你的论点:

    @Before("execution(* *(@CustomAnnotation (*)))")
    public void advice() {
    System.out.println("hello");
    }
    

    参考:http://forum.springsource.org/archive/index.php/t-61308.html

    在获取注释参数时:

    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    Annotation[][] methodAnnotations = method.getParameterAnnotations();
    

    将为您提供可以迭代的注释并使用 instanceof 来查找绑定的注释。我知道那很hacky,但afaik这是目前唯一支持的方式。

    【讨论】:

    • 注解后需加空格即@CustomAnnotation (*)
    【解决方案2】:

    要匹配 1..N 带注释的参数无论其位置如何,请使用

    编辑 2020-12-3:来自@sgflt 的简化版本

    @Before("execution(* *(.., @CustomAnnotation (*), ..))")
    public void advice(int arg1, @CustomAnnotation("val") Object arg2) { ... }
    

    【讨论】:

    • 它过于复杂。只需execution(* *(.., @CustomAnnotation (*), ..)) 就足够了。
    • 如果方法有多个注解如:public void advice(int arg1, @CustomAnnotation("val") @Custom2Annotation2("val") Object arg2) { ... } 会被解析吗?
    • 编辑:实际上它适用于任何数量的注释,我只是忘记将“@Component”注释放在方面类上!
    【解决方案3】:

    只是为了完成最后一个答案:

    @Before(value="execution(* *(@CustomAnnotation (*), ..)) && args(input, ..)")
    public void inspect(JoinPoint jp, Object input) {
            LOGGER.info(">>> inspecting "+input+" on "+jp.getTarget()+", "+jp.getSignature());
    }
    

    将匹配一个方法,其中方法的参数(之一)用@CustomAnnotation注释,例如:

    service.doJob(@CustomAnnotation Pojo arg0, String arg1);
    

    对比

    @Before(value="execution(* *(@CustomAnnotation *, ..)) && args(input, ..)")
    public void inspect(JoinPoint jp, Object input) {
                LOGGER.info(">>> inspecting "+input+" on "+jp.getTarget()+", "+jp.getSignature());
        }
    

    这将匹配参数的类(之一)用 @CustomAnnotation 注释的方法,例如:

    service.doJob(AnnotatedPojo arg0, String arg1);
    

    pojo 声明如下:

    @CustomAnnotation
    public class AnnotatedPojo {
    }
    

    所有区别都在于切入点声明中的@CustomAnnotation (*) 与@CustomAnnotation *。

    【讨论】:

    • 您确定“参数之一”吗?它会匹配service.doJob(String arg0, @CustomAnnotation Pojo arg1);吗?
    【解决方案4】:

    如果方法中有多个参数,则还应使用两个点来计算任意数量的参数(零个或多个)

    @Before("execution(* *(@CustomAnnotation (*), ..))")
    public void advice() {
        System.out.println("hello");
    }
    

    【讨论】:

      【解决方案5】:

      来自 Spring 文档:

      @Before("@annotation(myAnnotation)")
      public void audit(Auditable myAnnotation) {
        AuditCode code = auditable.value();
        // ...
      }
      

      这对我来说效果很好,无需操作方法签名。

      注意:如果您使用命名切入点,因为切入点名称可能被重载,您必须提供匹配的(参数名称和顺序)签名。

      @Before("goodAdvise(myAnnotation)")
      public void audit(Auditable myAnnotation) {
        String value = auditable.value();
        // ...
      }
      
      @Pointcut("@annotation(myAnnotation)")
      public void goodAdvise(Auditable myAnnotation) { 
        //empty
      }
      

      【讨论】:

      • @annotation 切入点指的是方法上的注解,而不是参数上的注解。
      猜你喜欢
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-24
      • 2011-02-20
      • 2011-12-10
      相关资源
      最近更新 更多