【发布时间】:2012-04-20 13:22:10
【问题描述】:
假设我有这样的方法:
public void method(@CustomAnnotation("value") String argument)
是否有一个切入点表达式可以选择所有带有@CustomAnnotation 注释的参数的方法?如果是这样,有没有办法让我访问“价值”参数?
【问题讨论】:
标签: spring aop spring-aop pointcut
假设我有这样的方法:
public void method(@CustomAnnotation("value") String argument)
是否有一个切入点表达式可以选择所有带有@CustomAnnotation 注释的参数的方法?如果是这样,有没有办法让我访问“价值”参数?
【问题讨论】:
标签: spring aop spring-aop pointcut
关于选择你的论点:
@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这是目前唯一支持的方式。
【讨论】:
要匹配 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) { ... } 会被解析吗?
只是为了完成最后一个答案:
@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);吗?
如果方法中有多个参数,则还应使用两个点来计算任意数量的参数(零个或多个)
@Before("execution(* *(@CustomAnnotation (*), ..))")
public void advice() {
System.out.println("hello");
}
【讨论】:
来自 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 切入点指的是方法上的注解,而不是参数上的注解。