2010-11-05 15 views
5

Ho un numero di pacchetti nella mia applicazione web Java. In alcuni di questi utilizzo questo costrutto:Dove definire un logger statico a livello di applicazione?

public class Foo { 
    private static Logger logger = LoggerFactory.getLogger("com.XXX"); 
    public void bar() { 
    Foo.logger.debug("Method bar() was just called"); 
    } 
} 

Naturalmente, è solo un esempio. Tutto funziona bene, ma non mi piace l'idea di inizializzazione del logger in molte classi. È un'ovvia duplicazione del codice. Vorrei spostarlo su qualche classe helper e consentire a tutte le altre classi di accedervi. È un'idea corretta? O forse ci sono altre "buone pratiche" o uno schema?

risposta

3

È possibile scrivere la propria classe di utilità che include il logger globale e implementa i delegati statici nei metodi del logger. Poi basta fare un'importazione statica di questa classe:

public class MyLogger { 
    private static Logger logger = LoggerFactory.getLogger("application"); 

    public static void debug(String s) {logger.debug(s));} 

    public static void debug(Class<?> caller, String s) { 
    LoggerFactory.getLogger(caller.getName()).debug(s); 
    } 

    // ... 
} 

Usage:

import static MyLogger.*; 

public class Foo { 
    public void bar() { 
    // makes use of static import! 
    debug("Method bar() was just called"); 
    debug(this.getClass(), "Method bar() was just called"); 
    } 
} 

Aggiunto una versione di overload dell'esempio debug delegato che prende un oggetto di classe e utilizza il Logger appropriata.

+1

Sì, si potrebbe. Ma il trucco si trova nella parte '' com.XXX' ', che viene normalmente utilizzata per segnalare da quale classe sta arrivando la voce del registro. Se non ti serve questo, puoi usare il tuo approccio. –

+0

come l'importazione statica! – dogbane

+0

@Andreas_D Sono d'accordo con Peter Knego. È possibile ottenere il nome della classe chiamante ('com.XXX.Foo' nell'esempio) all'interno del metodo' debug() '? – yegor256

0

È possibile creare un Adapter pattern per logger. Nel mio caso, ho esteso il logger per includere tutte le funzionalità del logger. Questo è poi trasformato in un Singleton.

public class LoggerAdapter extends Logger { 
    private LoggerAdapter instance; 
    private Logger logger; 

    private LoggerAdapter() { 

    } 

    public static LoggerAdapter getInstance(Clazz<?> clazz) { 
     if (instance == null) { 
      instance = new LoggerAdapter(); 
     } 
     instance.logger = logger = LoggerFactory.getLogger(clazz.getName()); 

     return instance; 
    } 

    @Override 
    public void trace(Object object) { 
     logger.trace(object); 
    } 

    //Other overridden methods here... 
}; 

In sostanza, un registratore di cambiamento dinamico ....

5

Non credo si vince nulla se utilizzati logger statico globale centralizzata constrcut diverso da quello comune Log4J chiama/INIT.

Se si scrive

private static Logger logger = LoggerFactory.getLogger("com.XXX"); 
logger.info("Hello World"); 

o qualcosa di simile

GlobalLogger.info(this, "LogMessage"); //Singleton... 

... non renderà il vostro codice più "leggibile".

1

Questo non è raccomandato poiché si perderanno le funzionalità di registrazione gerarchica di Log4j (se questo è ciò che si sta utilizzando), dove è molto utile aggiungere appendici diversi a diversi livelli dell'albero dei pacchetti. Non lo farei poiché si perderebbero informazioni su quale classe ha creato il messaggio di registro.

8

Dire che la duplicazione del codice è come dire che avere il numero import java.util.* nel 75% delle classi è la duplicazione del codice. Oppure ti ritrovi a scrivere public class ... troppo spesso. Non è una duplicazione della logica . Sta duplicando il codice boilerplate.

La duplicazione del codice è solo un design odore quando si tratta di duplicare la logica. Se c'è troppo codice di codice, è un odore di linguaggio nella lingua. Niente di cui dovresti davvero preoccuparti.

Sul lato negativo, si perde la possibilità di ottimizzare il registro se si abbandona la struttura gerarchica.

1

L'incapsulamento di una dipendenza di terze parti (ad esempio, Log4j) con una classe di utilità di registrazione ha senso.

Ad esempio, se un team decide di passare da Log4j a NextBigThingLogger, aggiorna semplicemente la classe MyLogger e nessuna delle altre classi dell'applicazione.

Pulizia e manutenzione più semplice.

Le API Apache e persino il linguaggio Java stesso sono piene di "odori di progettazione", ma ciò non significa che non dovremmo rispondere a esse.

Problemi correlati