2011-08-24 13 views
12

¿Cómo puedo escribir un punto de corte aspectj que se aplica a las ejecuciones de método que anulan un método de interfaz con una anotación? Por ejemplo:@AspectJ punto de corte para métodos que anulan un método de interfaz con una anotación

interface A { 
    @MyAnnotation void method(); 
} 
class B implements A { 
    void method(); 
} 

El punto de corte execution(@MyAnnotation * *.*(..)) sólo hace partido si B.method() lleva la anotación misma. Hay otra manera de hacer esto?

Respuesta

10

Como señaló Nicholas, esto no es posible en AspectJ. Aquí es una prueba más de por qué no es posible (tomado de http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html sección de anotación Herencia y coincidente pointcut):

acuerdo con la especificación Java 5, no de tipo anotaciones no se heredan, y anotaciones sobre los tipos son solamente heredado si tienen la meta-anotación @ Heredada. La llamada a c2.aMethod (que sería b.method() en su ejemplo) no coincide porque la coincidencia de punto de unión para modificadores (modificadores de visibilidad, anotaciones y cláusula throws) se basa en el sujeto del punto de unión (el método realmente llamado).

Al haber sufrido este mismo problema, he escrito un pequeño método/biblioteca que le permitiría escribir puntos de referencia para tales métodos.Aquí es cómo funcionaría para su ejemplo:

myAnnotationIsExecuted(): execution(public * *.*(..)) && 
      if(implementsAnnotation("@MyAnnotation()", thisJoinPoint)); 

O

myAnnotationIsExecuted(): execution(public * A+.*(..)) && 
      if(implementsAnnotation("@MyAnnotation()", thisJoinPoint)); 

El método implementsAnnotation(String,JoinPoint) proviene de la biblioteca; un método básico que verifica si los métodos implementados contienen la anotación especificada.

Más información acerca del método/biblioteca se puede encontrar here.

3

actualización

Dado que parece que no puede hacerse en primavera (ver respuesta original) Me gustaría decir que es necesario añadir la anotación a cada método en las clases que implementan. Hay una manera obvia de hacerlo, pero supongo que si estás buscando una forma más automática, necesitarás escribir una tú mismo.

Puedo imaginarme algún tipo de postprocesador de fabricación casera que buscará una anotación específica, digamos @ApplyThisAnnotationToAllWhoInheritMe. Una vez que encuentre esta anotación, escaneará el código fuente para heredar miembros y agregará la anotación solicitada cuando sea necesario antes de que se realice la compilación.

Independientemente, si está utilizando Spring AOP para hacer esto, parece que necesita estar en el método de implementadores. Si las clases que espera que esto ayude están fuera de su control, es posible que deba escribir su propia herramienta Spring AOP.

respuesta original

Desde el Spring 3.0 Documentation:

AspectJ sigue la regla de que las anotaciones de Java en las interfaces no se heredan.

me encontré con este bit en la sección 7.8.2 Other Spring aspects for AspectJ, que es una parte de 7.8 Using AspectJ with Spring applications, que me hace pensar que esto es una regla global.

+0

Gracias; eso explica por qué mi pointcut no funciona. Sin embargo, estoy buscando uno que funcione. :-) –

+0

@hstoerr: Después de editar su pregunta, edité mi respuesta. Avíseme si todavía es inaceptable. –

+1

La documentación de primavera en realidad no dice que es imposible hacer coincidir algo como lo que quiero, solo que el enfoque simple que probé no funciona. Puede que haya algo extraño que se pueda hacer en Aspectj que no se me ocurra. Así que todavía estoy esperando. :-) –

2
//introducing empty marker interface 
declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker; 

public pointcut p1() : execution(* TrackedParentMarker+.*(..)); 

También debe habilitar la bandera del compilador -XhasMember.

+0

Lamentablemente, eso no lo hace. Se aplica a todos los métodos de todas las clases que implementan una interfaz que tiene al menos un método que lleva la anotación. Pero debe aplicarse solo al método que implementa el método de interfaz con ese marcador. O al menos a los métodos que tienen el mismo nombre con el método de interfaz marcado, si eso es posible en AspectJ. –

Cuestiones relacionadas