Annotations de méthode nulles lors de l’utilisation de serveurs proxy via CGLIB

J’éprouve un comportement étrange lorsque je cherche dans la reflection des annotations sur une méthode appartenant à une classe proxy avec CGLIB. Nous utilisons CGLIB dans Spring et si j’annote une méthode uniquement avec une annotation, cela fonctionne bien (je suis en mesure de récupérer les annotations via la méthode getAnnotations() sur l’object Method correspondant). Si j’annote la méthode avec 2 annotations à la place (peu importe l’ordre des annotations), getAnnotations() ne fait que renvoyer null . Les deux annotations ont RetentionPolicy.RUNTIME .

J’ai lu qu’il y avait quelques problèmes avec CGLIB, mais il est étrange que cela fonctionne simplement pour une annotation et qu’il retourne null lorsque je mets 2 annotations.

Aucune suggestion?

(Utilisation de Spring 3.0.5 et CGLIB 2.2.2)

Ajout de code:

La première annotation est:

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Produces { ResultType[] value(); } 

2ème annotation est

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface JamonMonitored { Ssortingng type() default ""; Ssortingng tag() default ""; } 

Et le bloc de code est pour vérifier les annotations est

 Collection candidates = Collections2.filter(Arrays.asList(executorInstance.getClass().getMethods()), new Predicate() { @Override public boolean apply(Method input) { return input.getAnnotation(Produces.class) != null; } }); if (candidates.isEmpty()) { // throws exception } 

Si j’annote une méthode avec @Produces et @JamonMonitored, getAnnotation(Produces.class) est toujours null .

CGLIB fonctionne en générant une sous-classe de la classe de l’object cible et cette sous-classe a généré des méthodes qui déléguent à l’object cible. Lorsque vous utilisez la reflection pour interroger les annotations de l’object proxy, vous demandez des annotations sur la classe proxy, et non sur la classe de l’object cible.

Spring doit effectuer lui-même de nombreux traitements d’annotation afin de naviguer entre les proxies, les super-classes, les interfaces, etc. La logique pour ce faire est encapsulée et exposée dans la classe org.springframework.core.annotation.AnnotationUtils . Dans votre cas, il semble que vous souhaitiez findAnnotation méthode de l’utilitaire findAnnotation , c’est-à-dire

 @Override public boolean apply(Method input) { return AnnotationUtils.findAnnotation(input, Produces.class) != null; } 

Une autre option serait de spécifier @Inherited dans la définition des annotations. Cela ferait apparaître l’annotation même dans la sous-classe générée par cglib. Bien sûr, dans certains scénarios, vous ne voudriez pas que votre annotation apparaisse dans de “vraies” sous-classes, ce qui pourrait ne pas être une option pour tous les scénarios. La meilleure solution consiste à utiliser les aides Spring, comme le montre skaffman