2012-08-26 14 views
15

Java Guru,annotazioni personalizzate come Interceptor per un metodo di registrazione

Sono abbastanza nuovo per annotations e non hanno cercato per questo molto, quindi si prega di portare con me ...

vorrei implementare un Custom Annotation che chiamerà il metodo intercept; per iniziare con qualcosa di molto semplice, è sufficiente stampare il nome e i parametri dei metodi in modo da evitare l'istruzione logger.

Una chiamata di esempio in questo modo:

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

può essere convertito in:

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

Potrei avere alcuni suggerimenti su questo?

+0

Vuoi eseguire il codice di debug prima del metodo? – davidbuzatto

+0

In questo caso si. – SiB

+0

Ok. Mi sono dimenticato di chiedere. E questa esecuzione "prima" deve essere eseguita prima di ogni chiamata di metodo? – davidbuzatto

risposta

29

In base alle risposte dei miei commenti, non sarà possibile farlo con solo annotazioni. Puoi, ovviamente, creare le tue annotazioni e creare del codice riflettente che verrà rilevato e poi eseguire un codice, ma questo non cambierà troppo il tuo codice, perché dovrai chiamare il metodo parser prima di chiamare i tuoi metodi e credo questo non ti aiuterà troppo, dal momento che dovrai chiamare il metodo parser prima di ogni chiamata.

Se hai bisogno del comportamento che hai citato (chiamata automatica), dovrai combinare le tue annotazioni con qualche framework AOP come Spring (plain Java) o AspectJ (AspectJ code). Con quindi, è possibile impostare i collegamenti e ogni volta che viene raggiunto questo punto, può essere eseguito del codice. È possibile configurare quindi per eseguire alcuni codice prima e/o dopo l'esecuzione del metodo.

Se il primo scenario è sufficiente, si può fare qualcosa di simile:

Logger: enum

public enum Logger { 
    INFO, 
    DEBUG; 
} 

LogMethodCall della nota:

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: classe annotata

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); 
    } 

} 

Utils: classe con il metodo statico log (questa si esibirà il "parsing")

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: classe con il codice per verificare l'elaborazione di annotazione

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); 

    } 
} 

Ovviamente, dovrai migliorare il mio codice per soddisfare le tue esigenze. È solo un punto di partenza.

informazioni sulle annotazioni:

più su AOP:

+0

+1. Sì grazie. Grazie in anticipo – SiB

+0

Ok, il codice è completo. Provalo;) – davidbuzatto

+0

Lo farò; appena arrivo in ufficio ... ** Grazie mille ** per tutto il dolore che mi hai preso per aver scritto una così bella risposta !!! – SiB

1

come già suggerito, AOP e le annotazioni è l'opzione migliore. Mi sento di raccomandare di utilizzare un meccanismo di ready-made da jcabi-aspects (Sono uno sviluppatore):

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

Tutte le chiamate di metodo verrà registrato a SLF4J.

9

Utilizzare Spring AOP insieme a Java Annotation. Spring AOP annulla la necessità di scrivere una classe util per l'analisi delle classi Java utilizzando Java Reflection.

Esempio -

  1. personalizzato Annotazione -

    @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. Abilita AspectJ -

    @Configuration 
    @EnableAspectJAutoProxy 
    public class AConfig { 
    
    } 
    
  4. Uso in codice -

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

questa dovrebbe essere la risposta accettata. molto più semplice di sopra. –

Problemi correlati