Spring Точечный указатель AOP для аннотированного аргумента
Скажем, у меня есть такой метод:
public void method(@CustomAnnotation("value") String argument)
Есть ли выражение pointcut, которое могло бы выбрать все методы с аргументами, аннотированными с @CustomAnnotation? Если это так, я могу получить доступ к аргументу "значение"?
Ответы
Ответ 1
При выборе ваших аргументов:
@Before("execution(* *(@CustomAnnotation (*)))")
public void advice() {
System.out.println("hello");
}
ref: http://forum.springsource.org/archive/index.php/t-61308.html
При получении параметра аннотации:
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Annotation[][] methodAnnotations = method.getParameterAnnotations();
Вы получите аннотации, которые вы можете повторить и использовать instanceof, чтобы найти свою связанную аннотацию. Я знаю, что это взломанный, но афайк, это единственный способ, который поддерживается в настоящее время.
Ответ 2
Просто чтобы завершить последний ответ:
@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 *
в объявлении pointcut.
Ответ 3
Для сопоставления 1..N аннотированных аргументов независимо от их положения используйте
@Before("execution(* *(@CustomAnnotation (*), ..)) || " +
"execution(* *(.., @CustomAnnotation (*), ..)) || " +
"execution(* *(.., @CustomAnnotation (*)))")
public void advice(int arg1, @CustomAnnotation("val") Object arg2) { ... }
Ответ 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();
// ...
}
Это хорошо работает для меня, без необходимости манипулировать сигнатурой метода.
Примечание. Если вы используете именованный pointcut, потому что имена pointcut могут быть перегружены, вы должны указать подписи (имя параметра и порядок).
@Before("goodAdvise(myAnnotation)")
public void audit(Auditable myAnnotation) {
String value = auditable.value();
// ...
}
@Pointcut("@annotation(myAnnotation)")
public void goodAdvise(Auditable myAnnotation) {
//empty
}