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
}