2012-01-23 10 views
8

Tengo un comportamiento extraño cuando miro por reflejo las anotaciones de un método perteneciente a una clase con proxy vía CGLIB. Usamos CGLIB en Spring, y si anoto un método solo con una anotación, funciona bien (puedo recuperar las anotaciones a través del método getAnnotations() en el objeto correspondiente Method). Si anoto el método con 2 anotaciones (sin importar el orden de la anotación), getAnnotations() simplemente devuelva null. Ambas anotaciones tienen RetentionPolicy.RUNTIME.anotaciones de método nulas al enviar proxy a través de CGLIB

He leído que hay algunos problemas con CGLIB, pero es extraño que simplemente funcione para una anotación y devuelve nulo cuando coloco 2 anotaciones.

¿Alguna sugerencia?

(utilizando Spring 3.0.5 y 2.2.2 CGLIB)

Adición de código:

primera anotación es:

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

segunda anotación es

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

Y el el bloque de código es para comprobar las anotaciones es

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

if (candidates.isEmpty()) { 
    // throws exception 
} 

Si anoto un método con las dos @Produces y @JamonMonitored, getAnnotation(Produces.class) es siempre null.

+0

Puede proporcionar código . esto parece interesante, me gustaría echarle un vistazo. ¿Pero no he oído hablar de algo así, como el código? –

+0

Y espero que hayas pasado por este segmento real: http://stackoverflow.com/questions/1706751/retain-annotations-on-cglib-proxies –

Respuesta

14

CGLIB funciona al generar una subclase de la clase del objeto de destino, y esa subclase ha generado métodos que delegan en el objeto de destino. Cuando utiliza el reflejo para consultar las anotaciones del objeto proxy, está solicitando anotaciones en la clase de proxy, no en la clase del objeto de destino.

Spring tiene que hacer una gran cantidad de anotaciones para procesarse a sí misma con el fin de navegar en torno a proxies, superclases, interfaces y demás. La lógica para hacer esto está encapsulada y expuesta en la clase org.springframework.core.annotation.AnnotationUtils. En su caso, parece que desea que el findAnnotation utility method, es decir

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

¡Gracias, funcionó perfectamente! – manub

1

Otra opción sería especificar @Inherited dentro de la definición anotaciones. Esto haría que la anotación aparezca incluso en la subclase generada por cglib. Por supuesto, en algunos escenarios no le gustaría que su anotación aparezca en subclases "reales" por lo que esta podría no ser una opción para cada escenario y el camino a seguir es usar los ayudantes Spring como se muestra en skaffman

+0

Parece que no funciona, lo siento. Aunque desearía que sí. –

+0

@ Heredado solo funciona en clases, no en métodos – Phil

Cuestiones relacionadas