2012-08-28 19 views
35

Sto lavorando a un progetto e sto attualmente lavorando sull'implementazione di alcuni registri con log4j ed ero curioso di sapere come dovrei procedere per implementare i registri. Le due implementazioni sto calci in giro sono i seguenti:Registrazione Java con classi astratte

Prima Opzione

Usa registro unico dalla classe di super per quella classe e tutte le classi secondarie:

public abstract class AbstractFoo { 
    protected static Log LOG = LogFactory.getLog(AbstractFoo.class); 

    ... 
} 

public class Foo extends AbstractFoo { 
    public void someMethod() { 
     LOG.info("Using abstract log"); 
    } 
} 

Seconda Opzione

Utilizzare i registri individuali per ogni classe, super e sottotitoli:

public abstract class AbstractFoo { 
    private static Log LOG = LogFactory.getLog(AbstractFoo.class); 

    ... 
} 

public class Foo extends AbstractFoo { 
    private static Log LOG = LogFactory.getLog(Foo.class);   

    public void someMethod() { 
     LOG.info("Using own log"); 
    } 
} 

Cosa ha più senso e perché?

risposta

58

Non vorrei neanche. Invece farei usare la classe corretta in entrambi i casi.

public abstract class AbstractFoo { 
    protected final Log log = LogFactory.getLog(getClass()); 

    ... 
} 

public class Foo extends AbstractFoo { 
    public void someMethod() { 
     log.info("Using abstract log"); 
    } 
} 

Se non si esegue molta registrazione (che comunque è una buona idea) è possibile utilizzare un metodo.

Se esiste una classe che la chiama molto, è possibile sovrascriverla per fornire un'istanza memorizzata nella cache.

+1

Finora ho visto due approcci: logger statici (come nella domanda) e logger non statici (come nel tuo esempio). I logger statici non sono una soluzione migliore (un'istanza di logger per tutte le istanze)? I logger statici –

+4

sono migliori se sono uguali per tutte le istanze. Nel caso astratto della classe, la classe delle istanze non sono tutte uguali. –

+0

Mi piace, sembra un buon modo per combinare entrambe le opzioni.Si finisce con un singolo log ma si lega alla classe corretta. +1 – shuniar

2

Entrambi hanno senso. Dipende dalla tua applicazione.

Penso che la pratica più frequente sia quella di avere un logger privato per ogni classe. Ciò consente di configurare la registrazione sia per classe che per pacchetto. Ricorda che AbstractFoo e possono appartenere a pacchetti diversi e probabilmente vuoi vedere solo i registri da Foo.

Inoltre, pensa sempre due volte se desideri scrivere il campo protected. Non è completamente proibito, ma una pratica cattiva ben nota. Rende il tuo codice meno leggibile e difficile da mantenere.

1

Se si crea il logger nella classe astratta, i log verranno tutti etichettati come originati da AbstractFoo. Se si desidera/è necessario visualizzare i registri contrassegnati con la classe figlia da cui si è verificato il registro, creare i logger per le classi figlie.

+0

"Se si crea il logger nella classe astratta, i log verranno tutti etichettati come originati da AbstractFoo" -> No, non è vero se si utilizza la risposta accettata di @Peter_Lawrey. Quindi ottieni i log taggati con la classe che esegue la registrazione, sempre. – cellepo

+0

Il "problema" con la risposta di Lawrey è che ora sono logger basati su istanze, il che non è un'idea. – MeBigFatGuy

5

Questa è la mia soluzione (logger statica finale):

public abstract class AbstractFoo { 
    protected Log getLogger(); 
    public doSomething() { 
      getLogger().info("log something"); 
    } 
} 

public class Foo extends AbstractFoo { 
    private static final Log log = Log.getLogger(Foo.class); 

    protected Log getLogger() { 
     return log; 
    } 
    public doSomethingElse() { 
      log.info("log somethingElse"); 
    } 
} 
1

Lo stesso si può ottenere giocando con i costruttori. Aggiungere logger al Base livello di classe e impostare da ogni Derivato classe utilizzando super(). C'è il codice:

public abstract class AbstractFoo { 

    protected Log log; // base abstract class has a Log object. 

    public AbstractFoo(Log logger) { // parameterized constructor for logger, to be used by the derived class. 
     this.log = logger; 
    } 

    public doSomething() {  // common method for all the derived classes. 
     log.info("log something"); 
    } 
    // rest of business logic. 
} 

public class Foo extends AbstractFoo { 

    public Foo(){ 
     super(LogFactory.getLog(AbstractFoo.class)); 
    } 

    public void someMethod() { 
     log.info("Using own log");  // this uses its own logger. 
    } 
}