2012-08-28 25 views
35

Estoy trabajando en un proyecto, y actualmente estoy trabajando en la implementación de algunos registros con log4j y tenía curiosidad sobre cómo debería implementar los registros. Las dos implementaciones estoy dando vueltas son los siguientes:Registro de Java con clases abstractas

primera opción

Usa el registro sencillo del super clase para esa clase y todas las subclases:

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

segunda opción

Utilice registros individuales para cada clase, super y subs:

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

¿Qué tiene más sentido y por qué?

Respuesta

58

Yo tampoco. En cambio, haría que utilizara la clase correcta en ambos casos.

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

    ... 
} 

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

Si no está haciendo un montón de registros (que es una buena idea de todos modos) puede utilizar un método en su lugar.

public abstract class AbstractFoo { 
    protected Log log() { return LogFactory.getLog(getClass()); } 

    ... 
} 

Si hay una clase que llama a esto mucho, puede anularla para darle una instancia en caché.

+1

Hasta ahora he visto dos enfoques: registradores estáticos (como en la pregunta) y registradores no estáticos (como en su ejemplo). ¿Los madereros estáticos no son una mejor solución (una instancia de registrador por todas las instancias)? –

+4

loggers estáticos son mejores si son los mismos para todas las instancias. En el caso de la clase abstracta, la clase de las instancias no es la misma. –

+0

Me gusta esto, parece una buena manera de combinar ambas opciones.Usted termina con un solo registro, pero se une a la clase adecuada. +1 – shuniar

2

Ambos tienen sentido. Depende de su aplicación.

Creo que la práctica más utilizada es tener un registrador privado para cada clase. Esto le permite configurar el registro tanto por clase como por paquete. Recuerde que AbstractFoo y Foo pueden pertenecer a diferentes paquetes y, probablemente, desee ver los registros de Foo solamente.

Por otra parte siempre piense dos veces si quiere escribir el campo protected. No está completamente prohibido, pero es una mala práctica bien conocida. Hace que su código sea menos legible y difícil de mantener.

1

Si crea el registrador en la clase abstracta, todos los registros se etiquetarán como procedentes de AbstractFoo. Si desea/necesita ver registros etiquetados con la clase secundaria desde la cual se produjo el registro, cree registradores para las clases secundarias.

+0

"Si crea el registrador en la clase abstracta, todos los registros aparecerán etiquetados como procedentes de AbstractFoo" -> No, no es cierto si utiliza la Respuesta aceptada por @Peter_Lawrey. Luego obtienes registros etiquetados con clase haciendo el registro, siempre. – cellepo

+0

El 'problema' con la respuesta de Lawrey es que ahora son registradores basados ​​en instancias, lo cual no es una idea. – MeBigFatGuy

5

Esta es mi solución (registrador estático final):

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

El mismo se puede conseguir jugando con los constructores. Añadir registrador en el Base nivel de clase y configurarlo desde todos los Derivado clase utilizando super(). Está el código:

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. 
    } 
} 
Cuestiones relacionadas