2008-10-17 9 views
15

Cada clase que quiere usar java.util.logging general tiene que declarar un registrador de la siguiente manera:¿Cómo se reduce el código repetitivo del registro de Java?

public class MyClass { 
    private static Logger _log = Logger.getLogger(MyClass.class.getName()); 
} 

¿Cómo evitar este MyClass.class.getName) código repetitivo (?

+1

usted debe hacer el registrador definitiva instancia. –

+0

Uso una anotación @Trace para realizar el seguimiento de llamadas de método, es decir, registrar todos los argumentos y resultados/excepciones. Con esta biblioteca: https://github.com/nicholas22/jpropel –

Respuesta

12

Tengo una plantilla configurada en Eclipse para que solo tenga que escribir una parte de la declaración, y luego Eclipse automáticamente completará el resto.

${:import(org.apache.log4j.Logger)} 
private final static Logger log = Logger.getLogger(${enclosing_type}.class); 
${cursor} 

Por lo tanto, sólo tengo que escribir logger, HIT Ctrl+Space, seguido de Enter, y Eclipse rellena el resto para mí y añade la declaración de importación también.

Esto no reducirá la cantidad de código repetitivo, pero al menos reduce la cantidad de teclas presionadas.

+0

Acabo de hacer esto para JDE en Emacs. Gracias por la idea: al menos minimizará el dolor físico de la repetición. –

2

No necesita getName() si está utilizando una versión 1.2+ de log4j, getLogger() acepta un argumento de clase. Pero en cuanto al resto, no hay forma de evitarlo si desea que cada clase tenga un miembro de registro estático con su propia categoría.

+0

Otra forma de evitar esto es escribir un equivalente de getLogger que toma una clase y llama a getName en ella? –

+0

No está escribiendo un equivalente, está usando el método log4j org.apache.log4j.Logger # getLogger (clase clazz) que existe desde log4j 1.2. –

0

Puede taquicar esto un poquito, ya que getLogger está sobrecargado para simplemente tomar la clase. De la misma manera:

public class MyClass { 
    private static Logger _log = Logger.getLogger(MyClass.class); 
} 

El registrador puede ser tan flexible o inflexible como usted desee. Puede tomar un nuevo registrador para cada clase, como en su ejemplo anterior, y tener una jerarquía de registradores donde puede controlar y activar/desactivar el registro por clase. O si su proyecto es pequeño o un prototipo, etc., puede llamar a Logger.getRootLogger(), pero perderá la flexibilidad de ajustar lo que registra y no registra. Usted podría tener una clase base donde vive el registrador, y que todo el mundo llama que uno, pero de nuevo, se pierde algo de flexibilidad:

public class MyBase { 
    protected static Logger _log = Logger.getLogger(MyClass.class); 
} 

public class MyClass extends MyBase { 
    .... 
    _log.info("Stuff...."); 
} 

En pocas palabras, si desea mantener la capacidad de afinar configurar su registro más adelante en el proyecto (activar la depuración de nivel más fino para una sola clase), entonces puede que tenga que seguir con el estándar en todas las clases.

+0

su clase base está utilizando la clase incorrecta para crear el registrador. PERO, si lo arregló, ¿la clase secundaria no estaría registrando contra el registrador de la superclase? – davetron5000

-1

Si realiza el registrador no estático, al menos puede heredarlo:

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

public class SubClass extends SomeBaseClass 
{ 
    public void doit() { logger.debug("doit!!!!"); } 
} 

Así es como siempre he hecho.

+0

¿Esto no registra todos los mensajes contra SomeBaseClass? –

+0

No, getClass() devolverá la clase de tiempo de ejecución de un objeto –

+3

Pero el código en la clase padre/superclase se registrará con el registrador de la subclase. –

2

Si usted va para los madereros a nivel de paquete, con la adición de una clase repetitivo por paquete, se puede escribir:

private static final Logger log = Logs.log; 

Hay hacks para leer el nombre de la clase de la persona que llama (de hecho, la tala la implementación tiene un truco para detectar el método actual), pero no lo recomendaría.

3

Dependiendo de sus necesidades de registro, se podría crear una clase "LoggingService" con métodos estáticos para registrar a varios "canales". Descubrí que realmente no necesito granularidad de registro hasta el nivel de clase. Puede nombrar sus registradores lo que mejor funciona para usted. Hemos estado usando esto en aplicaciones empresariales grandes durante varios años y la granularidad realmente no ha sido un problema para nosotros.

El servicio de registro inicializado en un bloque inicializador estático ... así que entrar un mensaje:

LoggingService.logError ("bla");

No hay un código repetitivo en cada clase.

Aquí es un ejemplo de servicio de registro:

public class LoggingService { 

/** 
* A log for informational messages. 
*/ 
static private Logger infoLog; 

/** 
* A log for data access messages. 
*/ 
static private Logger dataAccessLog; 

/** 
* A log for debug messages. 
*/ 
static private Logger debugLog; 

/** 
* A log for error messages. 
*/ 
static private Logger errorLog; 

/** 
* A log for all XML related messages. 
*/ 
static private Logger xmlLog; 

/** 
* A log for all trace messages. 
*/ 
static private Logger traceLog; 

/** 
* A log for all warning messages. 
*/ 
static private Logger warnLog; 

static { 

    //This is the bootstrap for the logging service. 
    //Setup each logger 
    infoLog = Logger.getLogger("com.company.logging.info"); 
    dataAccessLog = Logger.getLogger("com.company.logging.dataaccess"); 
    debugLog = Logger.getLogger("com.company.logging.debug"); 
    errorLog = Logger.getLogger("com.company.logging.error"); 
    xmlLog = Logger.getLogger("com.company.logging.xml"); 
    traceLog = Logger.getLogger("com.company.logging.trace"); 
    warnLog = Logger.getLogger("com.company.logging.warn"); 

    // This must be set so isErrorEnabled() will work. 
    errorLog.setLevel(Level.ERROR); 
    warnLog.setLevel(Level.WARN); 
} 
static public void logDataAccess(String pMessage) { 
    dataAccessLog.info(pMessage); 
} 

static public void logInfo(String pMessage) { 
    infoLog.info(pMessage); 
} 

static public void logDebug(String pMessage) { 
    debugLog.debug(pMessage); 
} 

static public void logTrace(String pMessage) { 
    traceLog.debug(pMessage); 
} 

static public void logWarn(String pMessage) { 
    warnLog.warn(pMessage); 
} 

static public void logError(String pMessage) { 
    errorLog.error(pMessage); 
} 

static public void logError(String pMessage, Throwable pThrowable) { 
    errorLog.error(pMessage, pThrowable); 
} 

static public void logXml(String pMessage, XmlBean pContainer) { 

    if (!xmlLog.isInfoEnabled()) return; 

    xmlLog.info(pMessage + " : " + JAXBHelper.marshal(pContainer)); 
} 

static public boolean isInfoEnabled() { 
    return infoLog.isInfoEnabled(); 
} 

static public boolean isDataAccessEnabled() { 
    return dataAccessLog.isInfoEnabled(); 
} 

static public boolean isDebugEnabled() { 
    return debugLog.isDebugEnabled(); 
} 

static public boolean isErrorEnabled() { 
    if (errorLog.getLevel().toInt() >= Level.ERROR_INT) { 
     return true; 
    } 
    return false; 
} 

static public boolean isTraceEnabled() { 
    return traceLog.isDebugEnabled(); 
} 

static public boolean isXmlEnabled() { 
    return xmlLog.isInfoEnabled(); 
} 

static public boolean isWarnEnabled() { 
    return warnLog.isEnabledFor(Level.WARN); 
} 

}

+1

Supongo que esto podría funcionar para sus necesidades, pero personalmente no creo que el código del cliente necesite saber si el registro xml está habilitado, o si el registro de acceso a datos está habilitado. No parece una buena interfaz para mí. ¿Y por qué necesita registradores separados para cada nivel? Para cada uno, supongo. –

3

En realidad, la práctica común de utilizar nombres de las clases de nombres logger es perezoso más que nada.

La práctica mucho mejor es nombrar los registradores por el contexto de la tarea. Esto implica un poco más de proceso de pensamiento y planificación, pero al final, el resultado es una granularidad mucho más significativa, donde puede alternar los niveles de registro para las tareas reales en lugar de las clases.

+0

Ese es un buen punto. Aunque desde el punto de vista de un desarrollador, el registro del nombre de clase real es más fácil de usar para la depuración. Cuando se despliega en la producción y se supervisa, creo que su sugerencia es la mejor manera de hacerlo. –

+2

El inicio de sesión con el nombre de clase es un estándar de facto para el registro a nivel técnico. Usar el contexto lógico está bien, pero lo asocio más con el registro como un requisito comercial, es decir, algo así como la auditoría. –

1

Usted puede reducir eso y muchos otros códigos de caldera con Lombok

https://github.com/rzwitserloot/lombok

@Slf4j 
    public class LogExample { 
} 

habrá

public class LogExample { 
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class); 
} 
Cuestiones relacionadas