2012-08-26 23 views
15

Java Gurús,anotación personalizado como interceptor para un registro método

soy bastante nuevo para annotations y no han buscado mucho en esto, así que por favor tengan paciencia conmigo ...

me gustaría implementar un Custom Annotation que será intercept una llamada a un método; para comenzar con algo muy básico, puede imprimir el nombre y los parámetros de los métodos para poder evitar la declaración logger.

Un ejemplo de llamada de esta manera:

public MyAppObject findMyAppObjectById(Long id) throws MyCustomException { 
    log.debug("in findMyAppObjectById(" + id + ")"); 
    //.... 
} 

se puede convertir en:

@LogMethodCall(Logger.DEBUG) 
public MyAppObject findMyAppObjectById(Long id) throws MyCustomException { 
    //.... 
} 

podría conseguir algunas pistas acerca de esto?

+0

¿Quieres ejecutar el código de depuración antes de que el método? – davidbuzatto

+0

En este caso, sí. – SiB

+0

Ok. Olvide preguntar. Y esta ejecución "antes" debe realizarse antes de cada llamada al método? – davidbuzatto

Respuesta

29

Basado en sus respuestas de mis comentarios, no podrá hacer esto solo con anotaciones. Por supuesto, puede crear sus anotaciones y crear un código reflectante que luego se detectará y ejecutará algún código, pero esto no cambiará demasiado su código, porque tendrá que llamar al método parser antes de llamar a sus métodos y creo eso no te ayudará demasiado, ya que necesitarás llamar al método del analizador antes de cada llamada.

Si necesita el comportamiento que mencionó (llamada automática), deberá combinar sus anotaciones con algún marco AOP como Spring (plain Java) o AspectJ (código AspectJ). Con eso, puede establecer puntos de corte y cada vez que se alcanza este punto, se puede ejecutar algún código. Puede configurar luego para ejecutar algún código antes y/o después de la ejecución del método.

Si el primer escenario es suficiente, se puede hacer algo como:

Logger: enumeración

public enum Logger { 
    INFO, 
    DEBUG; 
} 

LogMethodCall: anotación

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) // the annotation will be available during runtime 
@Target(ElementType.METHOD)   // this can just used in methods 
public @interface LogMethodCall { 

    Logger logLevel() default Logger.INFO; 

} 

persona: la clase anotada

public class Person { 

    // will use the default log level (INFO) 
    @LogMethodCall 
    public void foo(int a) { 
     System.out.println("foo! " + a); 
    } 

    @LogMethodCall(logLevel = Logger.DEBUG) 
    public void bar(int b) { 
     System.out.println("bar! " + b); 
    } 

} 

Utilidades: clase con el método estático log (esto será realizar el "análisis")

public class Utils { 

    public static void log(Object o, String methodName) { 

     // gets the object class 
     Class klass = o.getClass(); 

     // iterate over its methods 
     for (Method m : klass.getMethods()) { 

      // verify if the method is the wanted one 
      if (m.getName().equals(methodName)) { 

       // yes, it is 
       // so, iterate over its annotations 
       for (Annotation a : m.getAnnotations()) { 

        // verify if it is a LogMethodCall annotation 
        if (a instanceof LogMethodCall) { 

         // yes, it is 
         // so, cast it 
         LogMethodCall lmc = (LogMethodCall) a; 

         // verify the log level 
         switch (lmc.logLevel()) { 
          case INFO: 
           System.out.println("performing info log for \"" + m.getName() + "\" method"); 
           break; 
          case DEBUG: 
           System.out.println("performing debug log for \"" + m.getName() + "\" method"); 
           break; 
         } 

        } 
       } 

       // method encountered, so the loop can be break 
       break; 

      } 

     } 

    } 

} 

AnnotationProcessing: clase con código para probar el procesamiento anotación

public class AnnotationProcessing { 

    public static void main(String[] args) { 

     Person p = new Person(); 
     Utils.log(p, "foo"); 
     p.foo(2); 
     Utils.log(p, "bar"); 
     p.bar(3); 

    } 
} 

Por supuesto, necesitará mejorar mi código para satisfacer sus necesidades. Es solo un punto de inicio.

Más sobre las anotaciones:

Más sobre AOP:

+0

+1. Sí por favor. Gracias de antemano – SiB

+0

Ok, el código está completo. Pruébalo;) – davidbuzatto

+0

Lo haré; tan pronto como llegue a la oficina ... ** Muchas gracias ** por todo el dolor que me ha tomado por escribir una respuesta tan agradable. – SiB

1

Como ya se ha sugerido, AOP y anotaciones es la mejor opción. Yo recomendaría utilizar un mecanismo confeccionada a partir jcabi-aspects (soy un desarrollador):

@Loggable(Loggable.DEBUG) 
public String load(URL url) { 
    return url.openConnection().getContent(); 
} 

Todas las llamadas de método se registrará en SLF4J.

9

Utilice Spring AOP junto con Java Annotation. Spring AOP niega el requisito de escribir una clase util para analizar las clases de Java utilizando Java Reflection.

Ejemplo -

  1. Custom Anotación -

    @Retention(RetentionPolicy.RUNTIME) 
    @Target(ElementType.METHOD) 
    public @interface A {    
        boolean startA() default false; 
    
        boolean endA() default false; 
    } 
    
  2. Aspect-

    @Aspect 
    public class AAspect { 
        @Pointcut(value = "execution(* *.*(..))") 
        public void allMethods() { 
          LOGGER.debug("Inside all methods"); 
        } 
    
        @Before("allMethods() && @annotation(A)")` 
        public void startAProcess(JoinPoint pjp, A a) throws Throwable { 
         if (a.startA()) { 
           //Do something 
        } 
    } 
    
  3. Habilitar AspectJ -

    @Configuration 
    @EnableAspectJAutoProxy 
    public class AConfig { 
    
    } 
    
  4. Uso de código -

    @A(startA = true, endA = true) 
    public void setUp(){ 
         //Do something- logic 
    } 
    
+0

esto realmente debería ser la respuesta aceptada. mucho más simple que arriba. –

Cuestiones relacionadas