J'ai une classe de service implémentée dans Java 6/Spring 3 qui nécessite une annotation pour restreindre l'accès par rôle.Point de coupure AOP de ressort qui correspond à l'annotation sur l'interface
J'ai défini une annotation appelée RequiredPermission qui a comme valeur de l'attribut une ou plusieurs valeurs d'un ENUM appelé 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
}
}
j'ai aussi la définition d'aspect suivant:
/**
* 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());
}
}
Le L'objet paramètre contient un nom d'utilisateur et je souhaite rechercher le rôle requis pour l'utilisateur avant de permettre l'accès à la méthode. Quand je mets l'annotation sur la méthode dans MyServiceImpl, tout fonctionne très bien, le pointcut est assorti et l'aspect intervient. Cependant, je crois que l'annotation fait partie du contrat de service et devrait être publiée avec l'interface dans un package API distinct. Et évidemment, je ne voudrais pas mettre l'annotation à la fois sur la définition de service et sur l'implémentation (DRY).
Je sais qu'il y a des cas dans Spring AOP où les aspects sont déclenchés par des annotations à une méthode d'interface (par exemple transactionnelle). Y a-t-il une syntaxe spéciale ici ou est-ce simplement impossible hors de la boîte. PS: Je n'ai pas posté ma config de printemps, car il semble fonctionner très bien. Et non, ce ne sont ni mes noms de classe ni de méthode d'origine.
PPS: En fait, voici la partie pertinente de ma config de printemps:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="com.mycompany.aspect.MyAspect">
<property name="userService" ref="userService" />
</bean>
Donc, si je comprends bien, la meilleure solution que vous avez trouvé pour votre question initiale (c.-à-ayant l'annotation dans le interface, pas dans la mise en œuvre) est de faire correspondre l'ensemble du paquet d'interfaces du fournisseur de services, puis introspecter sur le ProceedingJoinPoint afin de trouver les annotations de la méthode dans l'interface? Est-ce que c'est possible? C'est un très bon sujet, et je ne veux pas en commencer un nouveau avec la même question! Merci!! – espinchi
@espinchi J'étais tellement frustré que j'ai copié toutes les annotations de l'interface vers la classe d'implémentation et appliqué cela avec un test unitaire rigoureux qui vérifiait toutes les méthodes sur l'interface et la classe d'implémentation pour des annotations identiques. Pas exactement AOP, je sais. Je dirais que ça ne marche pas de manière fiable, après tout. –