2017-09-30 3 views
0

J'ai récemment ajouté AOP avec aspectJ et spring-aop à mon projet de printemps existant. Le but était d'intercepter les appels du contrôleur pour modifier la réponse qu'ils renvoyaient, afin de lier certaines valeurs à cette réponse que je ne voulais pas ajouter manuellement à chacun de mes contrôleurs, par exemple la date d'expiration du jeton réel utilisé par l'utilisateur final (que je n'ai même pas pu mettre en valeur dans mon contrôleur). J'ai réussi à le faire fonctionner jusqu'à ce que je commence mes tests unitaires:AspectJ avec Spring: les méthodes interceptées perdent leurs paramètres annotations

Dans mes tests unitaires, j'appelle directement mes méthodes de contrôleur en utilisant la fonction de réflexion de java, puis je répète le processus habituel (appel de la chaîne de filtres, du pré-gestionnaire et des gestionnaires de courrier, et la méthode du contrôleur elle-même qui est d'abord validée manuellement à l'aide du validateur à ressort lorsque l'annotation @Valid est présente sur l'un de mes paramètres.Tout ce processus fonctionne correctement et est exécuté correctement). Le problème est que maintenant que la méthode du contrôleur est interceptée par spring-aop, elle est mentionnée comme provenant du contrôleur proxy créé, et toutes les annotations de mes paramètres disparaissent. Voici un exemple de commande:

@Override 
public ResponseEntity<Object> editPassword(@Valid @RequestBody PasswordEditForm passwordEditForm, HttpServletRequest request) { 
    return factorizedUserBaseController.editPassword(passwordEditForm, request, User.class); 
} 

le paramètre PasswordEditForm a l'annotation @Valid donc dans mes cas de test, il a été validé avant toute autre étape, mais maintenant que je double vérifié, l'annotation @Valid n'est pas présent sur la méthode de proxy, et par conséquent le paramètre n'est pas validé, aucune idée pour résoudre ce problème et rendre mon annotation de paramètres encore compréhensible de mon point de vue de test? Remarque: lors de l'exécution du ressort via mvn spring-boot: run, les paramètres avec l'annotation @Valid sont correctement validés puis passent correctement à ma méthode de gestionnaire d'erreurs.

Répondre

0

Problème résolu: à partir de plusieurs autres posts de stackoverflow, je comprends que CGLIB (aop proxy lib utilisé par Spring) ne supporte pas les annotations. (Voir Retain annotations on CGLIB proxies?). Mais mon problème n'était pas là, j'étais littéralement sûr de trouver la méthode en utilisant la classe de contrôleur elle-même (celle que j'ai codée) mais ce dont j'avais tort, c'est que je donnais l'instance de contrôleur comme paramètre à d'autres parties de mon code qui à son tour utiliserait cette classe de contrôleur pour trouver la méthode qui bien sûr ne fonctionnait pas car grâce aux procurations de Spring, ce n'était plus mon contrôleur lui-même mais une classe proxy étendant ma propre classe de contrôleur. Au lieu de cela, je devais juste remplacer:

Class<?> controllerClass = controllerInstanciationContainer 
      .getController() 
      .getClass(); 

avec

Class<?> controllerClass = controllerInstanciationContainer 
      .getController() 
      .getClass() 
      .getSuperclass(); 
+0

Je vous conseille d'aller tout et utiliser AspectJ au lieu du printemps AOP. Spring AOP avec sa solution basée sur un proxy est beaucoup moins capable que le bytecode direct manipulant AspectJ. –

+0

Je ne savais pas qu'il était même possible d'utiliser Spring avec All-in AspectJ! Je pensais que ce n'était pas possible et c'est pourquoi Spring a développé sa librairie printanière. Merci pour votre commentaire, je vais jeter un coup d'oeil à cette possibilité, car en regardant les tas, j'ai été impressionné par le nombre de pas à faire pour que ce petit morceau de bytecode soit exécuté ... –