Tengo una clase de servicio implementada en Java 6/Spring 3 que necesita una anotación para restringir el acceso por rol.Punto de corte AOP Spring que coincide con la anotación en la interfaz
he definido un llamado RequiredPermission anotación que tiene como su valor de atributo uno o más valores de una enumeración llamado 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
}
}
I también tienen la siguiente definición aspecto:
/**
* 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());
}
}
El El objeto parámetro contiene un nombre de usuario y quiero buscar el rol requerido para el usuario antes de permitir el acceso al método.
Cuando pongo la anotación en el método en MyServiceImpl, todo funciona bien, el pointcut es coincidente y el aspecto entra en acción. Sin embargo, creo que la anotación es parte del contrato de servicio y debe publicarse con la interfaz en un paquete API por separado Y obviamente, no me gustaría poner la anotación tanto en la definición del servicio como en la implementación (DRY).
Sé que hay casos en Spring AOP donde los aspectos se activan mediante las anotaciones de un método de interfaz (por ejemplo, Transactional). ¿Hay una sintaxis especial aquí o es simplemente imposible de usar?
PD: No he publicado mi configuración de muelles, ya que parece estar funcionando bien. Y no, esos no son mis nombres originales de clase o método.
PPS: En realidad, esta es la parte pertinente de mi config primavera:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="com.mycompany.aspect.MyAspect">
<property name="userService" ref="userService" />
</bean>
lo tanto, si he entendido bien, la mejor solución que encontró para su pregunta original (es decir, con la anotación en el interfaz, no en la implementación) es hacer coincidir todo el paquete de interfaces del proveedor de servicios, y luego introspectivamente en el ProceedingJoinPoint con el fin de encontrar las anotaciones del método en la interfaz. ¿Es eso posible? ¡Este es un gran hilo, y no quiero comenzar uno nuevo con la misma pregunta! ¡¡Gracias!! – espinchi
@espinchi en realidad estaba tan frustrado que copié todas las anotaciones de la interfaz a la clase de implementación y lo hice cumplir con una rigurosa prueba de unidad que verificaba todos los métodos tanto en la interfaz como en la clase de implementación para anotaciones idénticas. No exactamente AOP, lo sé. Diría que no funciona de manera confiable, después de todo –