Este tutorial de Mkyong sugiere iniciar loggers 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, inicializará sus registradores de la misma manera.
Mi pregunta es: ¿es esta la mejor manera de hacerlo? Parece ... repetitivo.
getLogger()
el nombre del registrador para obtener.Respuestas:
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 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 un registro. Dicho esto, la línea específica de código que está utilizando es propensa a copiar y pegar errores (más sobre eso más adelante).
Pero, dado que desea alternativas, aquí hay algunas, con razones por las que puede querer o no usarlas.
Use un solo registrador para toda la aplicación
Si no le importa qué clase está informando, o está dispuesto a poner todo el contexto necesario en el mensaje, un simple registrador de singleton hará el trabajo:
En mi opinión, uno de los grandes beneficios de un marco de registro es tener el contexto proporcionado por instancias de registrador separadas, aunque solo sea para dirigir los mensajes de registro a diferentes destinos. No renunciaría a eso solo para guardar una línea de código (aún necesita la importación).
Además, esto aumenta la verbosidad en el punto de uso, lo que terminará en muchas más pulsaciones de teclas.
Crea tus registradores en el punto de uso
Estoy descartando esto solo porque elimina la variable. No creo que necesite comentarlo. Aunque muestra mi técnica preferida para obtener una instancia de registrador.
Use un postprocesador de frijoles para inyectar el registrador
Su ejemplo usa Spring, y Spring le permite conectar el código de inicialización del bean. Podría crear un postprocesador que inspeccione el bean en busca de una
logger
variable miembro y cree unaLogger
instancia cuando encuentre una.Si bien dicho postprocesador es solo unas pocas docenas de líneas de código, es otra parte móvil de su aplicación y, por lo tanto, otra fuente potencial de errores. Prefiero tener la menor cantidad posible.
Usa un mixin
Scala y Groovy proporcionan rasgos que le permiten encapsular el comportamiento. Un patrón típico de Scala es crear un
Logging
rasgo y luego agregarlo a la clase que necesita registro:Desafortunadamente, esto significa que tienes que cambiar de idioma. A menos que esté utilizando Java 8, en cuyo caso puede crear una
Logging
interfaz con un "método predeterminado":Ahora, dentro de su código de clase, simplemente puede usar
Si bien es fácil, esto tiene un par de desventajas. Por un lado, contamina la interfaz de cada clase que lo usa, porque todos los métodos de interfaz son públicos. Tal vez no sea tan malo si lo usa solo para clases que Spring instancia e inyecta, especialmente si sigue la separación de interfaz / implementación.
El mayor problema es que tiene que buscar la instancia de registrador real en cada llamada. Lo cual es rápido, pero innecesario.
Y aún necesita una declaración de importación.
Mover el registrador a una superclase
Repetiré: no encuentro definiciones de registrador repetidas detalladas, pero si lo hace, creo que este es el mejor enfoque para eliminarlas.
Ahora sus clases de controlador heredan
AbstractController
y tienen acceso a lalogger
variable. Recuerda que tienes que poner la@Controller
anotación en la clase concreta.Algunas personas encontrarán esto como una perversión de la herencia. He tratado de aplacarlos nombrando la clase en
AbstractController
lugar deAbstractProjectClass
. Puedes decidir por ti mismo si existe o no una relación es-es .Otras personas se opondrán al uso de una variable de instancia en lugar de una variable estática. Los registradores estáticos de IMO son propensos a copiar y pegar errores, ya que debe hacer referencia explícita al nombre de clase;
getClass()
asegura que su registrador sea siempre correcto.fuente
MethodHandles.lookup().lookupClass()
es mejor queObject.getClass()
?MethodHandles.lookup().lookupClass()
se puede usar para variables estáticas, no es propenso a copiar y pegar errores y es rápido: stackoverflow.com/a/47112323/898747 Significa un ingreso adicional, pero me gusta que mis registradores sean estáticos, por lo que al menos vale la pena mención :)Para ampliar la respuesta proporcionada por @kdgregory, Groovy proporciona
@Slf4j
(groovy.util.logging.Slf4j
) fuera de la caja como una anotación que realiza una transformación AST en la clase para agregarla con un registrador que asume el nombre de la variablelog
por defecto si no se especifica.fuente