Spring Точечный указатель AOP, который соответствует аннотации на интерфейсе
У меня есть класс обслуживания, реализованный в Java 6/ Spring 3, который требует аннотации для ограничения доступа по ролям.
Я определил аннотацию, называемую RequiredPermission, которая имеет в качестве атрибута value одно или несколько значений из перечисления, называемого OperationType:
public @interface RequiredPermission {
/**
* One or more {@link OperationType}s that map to the permissions required
* to execute this method.
*
* @return
*/
OperationType[] value();}
public enum OperationType {
TYPE1,
TYPE2;
}
package com.mycompany.myservice;
public interface MyService{
@RequiredPermission(OperationType.TYPE1)
void myMethod( MyParameterObject obj );
}
package com.mycompany.myserviceimpl;
public class MyServiceImpl implements MyService{
public myMethod( MyParameterObject obj ){
// do stuff here
}
}
У меня также есть следующее определение аспекта:
/**
* Security advice around methods that are annotated with
* {@link RequiredPermission}.
*
* @param pjp
* @param param
* @param requiredPermission
* @return
* @throws Throwable
*/
@Around(value = "execution(public *"
+ " com.mycompany.myserviceimpl.*(..))"
+ " && args(param)" + // parameter object
" && @annotation( requiredPermission )" // permission annotation
, argNames = "param,requiredPermission")
public Object processRequest(final ProceedingJoinPoint pjp,
final MyParameterObject param,
final RequiredPermission requiredPermission) throws Throwable {
if(userService.userHasRoles(param.getUsername(),requiredPermission.values()){
return pjp.proceed();
}else{
throw new SorryButYouAreNotAllowedToDoThatException(
param.getUsername(),requiredPermission.value());
}
}
Объект параметра содержит имя пользователя, и я хочу найти нужную роль для пользователя, прежде чем разрешить доступ к этому методу.
Когда я добавляю аннотацию к методу в MyServiceImpl, все работает очень хорошо, привязка pointcut и нос. Но я считаю, что аннотация является частью контракта на обслуживание и должна публиковаться с интерфейсом в отдельный пакет API. И, очевидно, я бы не хотел помещать аннотацию на определение и реализацию сервиса (DRY).
Я знаю, что есть случаи в Spring AOP, где аспекты запускаются с помощью аннотаций на один из методов интерфейса (например, Transactional). Есть ли специальный синтаксис здесь или это просто невозможно из коробки.
PS: Я не размещал свой конфигуратор Spring, так как он работает нормально. И нет, это не мои первоначальные классы и имена методов.
PPS: На самом деле, вот соответствующая часть моей конфигурации Spring:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="com.mycompany.aspect.MyAspect">
<property name="userService" ref="userService" />
</bean>
Ответы
Ответ 1
Если вы правильно поняли, вам нужен pointcut, который найдет все методы в классах, которые расширят MyService и будут аннотированы и с предпочтительными аргументами.
Я предлагаю заменить:
execution(public * com.mycompany.myserviceimpl.*(..))
с:
execution(public * com.mycompany.myservice.MyService+.*(..))
Знак плюса используется, если вы хотите, чтобы точка соединения соответствовала классу MyService или классу, который его расширяет.
Надеюсь, это поможет!
Ответ 2
Espen, ваш код работает только для одного класса:
execution(public * com.mycompany.myservice.MyService+.*(..))
но что, если я хочу этого поведения для всех сервисов в пакете com.mycompany.services. **?
Ответ 3
У меня был успех при таком подходе:
http://nonrepeatable.blogspot.co.uk/2010/05/validating-service-method-parameters.html
Ответ 4
Я столкнулся с той же проблемой, однако приведенные выше предложения не помогают.
Если у меня есть это только как pointcut:
execution(public * com.mycompany.myservice.MyService+.*(..))
Затем вызывается совет. Однако, если я добавлю это:
&& @annotation(x.y.z.Logged)
Тогда совет не вызывается. Интерфейс MyService содержит аннотацию @Logged по одному из своих методов и даже по объявлению типа.
Ответ 5
Вы должны добавить аннотацию @Inherited в свою аннотацию @RequiredPermission.
http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html