Logger.getLogger (MyClass.class) è il modo migliore per inizializzare i logger log4j?

7

Questo tutorial di Mkyong suggerisce i logger intialising in questo modo:

@Controller
public class WelcomeController {

    private static final Logger logger = Logger.getLogger(WelcomeController.class);

   // etc

}

Ora presumibilmente ogni altra classe che usi, che ha un logger che inizializza i loro logger nello stesso modo.

La mia domanda è - è questo il modo migliore per farlo? Sembra ... ripetitivo.

    
posta dwjohnston 26.06.2015 - 03:12
fonte

1 risposta

13

Il tuo commento dice che "verbose" si riferisce alla necessità di ripetere questa riga di codice in ogni classe. La mia prima risposta è che, nel quadro generale, l'aggiunta di due righe di codice (definizione delle variabili più istruzioni di importazione) per ogni classe non è un grosso problema. Soprattutto perché devi solo aggiungerli alle classi che hanno un comportamento e quindi devono fare il logging. Detto questo, la linea di codice specifica che stai utilizzando è incline agli errori di copia-incolla (ne parleremo più avanti).

Ma, dal momento che vuoi delle alternative, eccone alcune, con le ragioni per cui potresti o non vorresti usarle.

Utilizza un singolo registratore per l'intera app

Se non ti importa di cosa la classe sta segnalando, o sei disposto a mettere tutto il contesto necessario nel messaggio, allora un semplice logger singleton farà il lavoro:

LoggerSingleton.getInstance().debug("MyController is running")

A mio parere, uno dei grandi vantaggi di un framework di registrazione è il fatto che il contesto sia fornito da istanze di logger separate, se non altro per indirizzare i messaggi di log verso destinazioni diverse. Non vorrei rinunciare solo per salvare una riga di codice (hai ancora bisogno dell'importazione).

Inoltre, questo aumenta la verbosità al punto di utilizzo, che finirà con un numero molto maggiore di combinazioni di tasti.

Crea i tuoi logger nel punto di utilizzo

Sto buttando questo fuori solo perché elimina la variabile. Non penso di aver bisogno di commentarlo. Sebbene mostri la mia tecnica preferita per ottenere un'istanza del logger.

Logger.getLogger(getClass()).debug("blah blah blah");

Utilizza un post-processore del bean per iniettare il logger

Il tuo esempio usa Spring e Spring ti permette di collegarti al codice di inizializzazione del bean. Puoi creare un post-processore che ispeziona il bean per una variabile membro logger e crea un'istanza Logger quando ne trova uno.

Mentre un post-processore di questo tipo è composto da poche decine di righe di codice, è un'altra parte mobile della tua applicazione, e quindi un'altra potenziale fonte di bug. Preferisco avere il minor numero possibile di quelli.

Utilizza un mixin

Scala e Groovy forniscono tratti , che ti consentono di incapsulare il comportamento. Un tipico pattern di Scala consiste nel creare un tratto di Logging , quindi aggiungerlo alla classe che richiede la registrazione:

class MyController with Logging

Sfortunatamente, questo significa che devi cambiare lingua. A meno che tu non stia utilizzando Java 8, nel qual caso puoi creare un'interfaccia Logging con un "metodo predefinito":

public interface Logging {
    default Logger getLogger() {
        return Logger.getLogger(getClass());
    } 
}

Ora, all'interno del codice della classe, puoi semplicemente usare

getLogger().debug("blah blah blah");

Sebbene facile, questo ha un paio di svantaggi. Per prima cosa, inquina l'interfaccia di ogni classe che la usa, perché tutti i metodi di interfaccia sono pubblici. Forse non così male se lo usi solo per le classi che sono istanziate e iniettate da Spring, specialmente se segui la separazione interfaccia / implementazione.

Il problema più grande è che deve cercare l'istanza del registratore reale su ogni chiamata. Che è veloce, ma non necessario.

E hai ancora bisogno di una dichiarazione di importazione.

Sposta il registratore su una superclasse

Ripeterò: non trovo verbose le definizioni del logger ripetute, ma se lo fai penso che questo sia l'approccio migliore per eliminarle.

public abstract class AbstractController {
    protected Logger logger = Logger.getLogger(getClass());
}

Ora le tue classi di controller ereditano da AbstractController e hanno accesso alla variabile logger . Ricorda che devi mettere l'annotazione @Controller sulla classe concreta.

Alcune persone troveranno questa una perversione dell'eredità. Ho provato a renderli più semplici nominando la classe AbstractController piuttosto che AbstractProjectClass . Puoi decidere autonomamente se esiste una relazione è-a .

Altre persone obietteranno all'utilizzo di una variabile di istanza piuttosto che di una variabile statica. IMO i logger statici sono inclini agli errori di copia-incolla, perché devi fare esplicito riferimento al nome della classe; getClass() garantisce che il tuo logger sia sempre corretto.

    
risposta data 27.06.2015 - 13:58
fonte

Leggi altre domande sui tag