Spring AOP中用于注释参数的切入点

21

假设我有一个如下所示的方法:

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

是否有切入点表达式可以选择所有带有@CustomAnnotation注释的参数方法?如果有,我能否访问"value"参数?

5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
25

选择参数时:

@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查找绑定的注释。我知道这很糊弄,但据我所知,这是目前唯一支持的方法。


4
注释后面需要加一个空格,即@CustomAnnotation (*)。 - Christopher Yang

11

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

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

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

6
过于复杂了。只需要 execution(* *(.., @CustomAnnotation (*), ..)) 就足够了。 - sgflt
如果方法有多个注释,例如: public void advice(int arg1, @CustomAnnotation("val") @Custom2Annotation2("val") Object arg2) { ... } 它也会被解析吗? - Fábio Araújo
实际上,它适用于任何数量的注释,我只是忘记在切面类上放置“@Component”注释! - Fábio Araújo

7

仅为了补充上一个答案:

@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 *。请注意,括号中的星号表示只匹配具有参数的注释,而不带括号的星号将匹配所有使用该注释的代码。

你确定 "one of arguments" 吗?它会匹配 service.doJob(String arg0, @CustomAnnotation Pojo arg1); 吗? - izogfif

1
如果一个方法有多个参数,您应该使用两个点号来匹配任意数量的参数(零个或多个)。
@Before("execution(* *(@CustomAnnotation (*), ..))")
public void advice() {
    System.out.println("hello");
}

-1

来自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
}

2
@annotation 切入点是指方法上的注解,而不是参数上的注解。 - Adam Michalik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,