Spring AOP: как получить аннотации рекомендуемого метода

Я хотел бы реализовать декларативную безопасность с помощью Spring/AOP и аннотаций. Как вы видите в следующем примере кода, у меня есть Ограниченные аннотации с параметром "allowedRoles" для определения того, кому разрешено выполнять рекомендуемый метод.

    @Restricted(allowedRoles="jira-administrators")
        public void setPassword(...) throws UserMgmtException {             
               // set password code
               ...
        }

Теперь проблема заключается в том, что в моем совете у меня нет доступа к определенным аннотациям:

public Object checkPermission(ProceedingJoinPoint pjp) throws Throwable {

    Signature signature = pjp.getSignature();
    System.out.println("Allowed:" + rolesAllowedForJoinPoint(pjp));
            ...
}

private Restricted rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint)
        {
            MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
            Method targetMethod = methodSignature.getMethod();

            return targetMethod.getAnnotation(Restricted.class);
        }

Метод выше всегда возвращает значение null (вообще не существует аннотаций). Есть ли простое решение?

Я прочитал что-то об использовании агента AspectJ, но я бы предпочел не использовать этот агент.

Ответы

Ответ 1

Я предполагаю, что @Restricted - ваша аннотация. Если это так, убедитесь, что у вас есть:

@Retention(RetentionPolicy.RUNTIME)

в определении аннотации. Это означает, что аннотация сохраняется во время выполнения.

Ответ 2

Для тех, у кого еще есть проблема после изменения аннотации к Runtime, у вас может быть такая же проблема: getMethod() возвращает метод интерфейса вместо класса реализации. Итак, если у вас есть аннотации в классе, то, естественно, метод getAnnotations() в методе интерфейса возвращает null.

Следующее решение решило эту проблему:

final String methodName = pjp.getSignature().getName();
final MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
Method method = methodSignature.getMethod();
if (method.getDeclaringClass().isInterface()) {
    method = pjp.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());    
}

и если вам нравится, у вас есть возможность обрабатывать аннотации интерфейса здесь тоже.

Еще несколько комментариев доступны здесь: Получение экземпляра метода шаблона из ProceedingJoinPoint

Олег

Ответ 3

Даже после изменения политики хранения, как сказал Божо, этот вызов для получения аннотации возвращает null:

targetMethod.getAnnotation(Restricted.class);

Что я нашел, вам нужно связать аннотацию. Учитывая, что интерфейс объявлен следующим образом:

 @Retention(RetentionPolicy.RUNTIME)
 public @interface Restricted {
     String[] allowedRoles();
  }

Совет должен быть объявлен следующим образом:

       @Before("@annotation( restrictedAnnotation )")
       public Object processRequest(final ProceedingJoinPoint pjp, Restricted restrictedAnnotation) throws Throwable {
                  String[] roles = restrictedAnnotation.allowedRoles();
                  System.out.println("Allowed:" +  roles);
       }

То, что это делает, - привязать аннотацию к параметру в сигнатуре метода, limitedAnnotation. Часть, о которой я не уверен, это то, как она получает тип аннотации, она, по-видимому, основана на параметре. И как только вы получите аннотацию, вы можете получить значения.

Ответ 4

Почему бы вам просто не использовать Spring Безопасность? Это краткое введение и использование, я действительно не вижу смысла тратить время на создание колеса.

Ответ 5

С Spring AOP, если у вас есть такая ситуация, как MyManagerImpl implements MyManager, метод pointcut применяется к методу interface, поэтому MethodSignature описывает метод, определенный в MyManager, который не имеет никакой аннотации. единственный способ найти это - проверить класс объекта jp.getTarget() и получить соответствующий метод.