¿Es Logger.getLogger (MyClass.class) la mejor manera de inicializar los loggers log4j?

7

Este tutorial de Mkyong sugiere intializar registradores de esta manera:

@Controller
public class WelcomeController {

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

   // etc

}

Ahora, presumiblemente, cualquier otra clase que use, que tenga un registrador, iniciará sus registradores de la misma manera.

Mi pregunta es: ¿es esta la mejor manera de hacerlo? Parece ... repetitivo.

    
pregunta dwjohnston 26.06.2015 - 03:12

1 respuesta

13

Su comentario dice que "detallado" se refiere a la necesidad de repetir esta línea de código en cada clase. Mi primera respuesta es que, en general, agregar dos líneas de código (definición de variable más declaración de importación) a cada clase no es tan importante. Especialmente porque solo necesita agregarlos a las clases que tienen comportamiento y, por lo tanto, necesita hacer el registro. Dicho esto, la línea específica de código que estás usando es propensa a copiar y pegar errores (más sobre esto más adelante).

Pero, como desea alternativas, aquí hay algunas, con razones por las que podría o no desear usarlas.

Utilice un único registrador para toda la aplicación

Si no te importa qué clase está informando, o estás dispuesto a poner todo el contexto necesario en el mensaje, entonces un simple registrador Singleton hará el trabajo:

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

En mi opinión, uno de los grandes beneficios de un marco de registro es tener el contexto proporcionado por instancias de registrador independientes, aunque solo sea para dirigir los mensajes de registro a diferentes destinos. No lo dejaría solo para guardar una línea de código (todavía necesitas la importación).

Además, esto aumenta la verbosidad en el punto de uso, lo que terminará en muchas más pulsaciones de teclas.

Cree sus registradores en el punto de uso

Estoy desechando este solo porque elimina la variable. No creo que tenga que comentarlo. Aunque muestra mi técnica preferida para obtener una instancia de registrador.

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

Utilice un postprocesador de bean para inyectar el registrador

Su ejemplo utiliza Spring, y Spring le permite enlazar con el código de inicialización del bean. Podría crear un postprocesador que inspeccione el bean para una variable miembro logger y cree una instancia Logger cuando encuentre una.

Si bien dicho post-procesador tiene solo unas pocas docenas de líneas de código, es otra parte móvil en su aplicación y, por lo tanto, otra fuente potencial de errores. Prefiero tener la menor cantidad posible de esos.

Usar una mezcla

Scala y Groovy proporcionan rasgos , que te permiten encapsular el comportamiento. Un patrón típico de Scala es crear un rasgo Logging , luego agregarlo a la clase que necesita registro:

class MyController with Logging

Lamentablemente, esto significa que tienes que cambiar de idioma. A menos que esté utilizando Java 8, en cuyo caso puede crear una interfaz Logging con un "método predeterminado":

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

Ahora, dentro de su código de clase, simplemente puede usar

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

Aunque es fácil, esto tiene un par de desventajas. Por un lado, contamina la interfaz de cada clase que la usa, porque todos los métodos de interfaz son públicos. Quizás no sea tan malo si lo usa solo para las clases que Spring crea y crea una instancia de ellas, especialmente si sigue la separación entre la interfaz y la implementación.

El mayor problema es que tiene que buscar la instancia del registrador real en cada llamada. Que es rápido, pero innecesario.

Y todavía necesitas una declaración de importación.

Mover el registrador a una superclase

Repetiré: no encuentro definiciones de logger repetidas, pero si lo hace, creo que este es el mejor enfoque para eliminarlas.

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

Ahora sus clases de controlador heredan de AbstractController , y tienen acceso a la variable logger . Recuerde que debe colocar la anotación @Controller en la clase concreta.

Algunas personas encontrarán esto como una perversión de la herencia. He intentado aplacarlos nombrando la clase AbstractController en lugar de AbstractProjectClass . Puedes decidir por ti mismo si hay o no una relación is-a .

Otras personas objetarán el uso de una variable de instancia en lugar de una variable estática. IMO los registradores estáticos son propensos a copiar y pegar errores, porque tiene que hacer referencia explícita a nombre de la clase; getClass() garantiza que su registrador esté siempre correcto.

    
respondido por el kdgregory 27.06.2015 - 13:58

Lea otras preguntas en las etiquetas