2008-10-17 7 views
15

Chaque classe qui veut utiliser java.util.logging a généralement besoin de déclarer un enregistreur comme celui-ci:Comment réduire le code standard Java?

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

Comment éviter ce MyClass.class.getName() code passe-partout?

+1

Vous devriez faire la finale de l'instance de l'enregistreur. –

+0

J'utilise une annotation @Trace pour effectuer un traçage d'appel de méthode, c'est-à-dire consigner tous les arguments et résultats/exceptions. Avec cette bibliothèque: https://github.com/nicholas22/jpropel –

Répondre

12

J'ai un modèle mis en place dans Eclipse de sorte que je n'ai qu'à taper une partie de la déclaration, puis Eclipse va auto-compléter le reste pour moi.

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

Alors, je ne taper logger, frappé Ctrl+Space, suivi par Enter et Eclipse Remplit le reste pour moi et ajoute la déclaration d'importation ainsi.

Cela ne réduira pas la quantité de code standard, mais au moins, il réduira le nombre de frappes.

+0

Je viens de le faire pour JDE dans Emacs. Merci pour l'idée - il va au moins minimiser la douleur physique de la plaque. –

2

Vous n'avez pas besoin de getName() si vous utilisez une version 1.2+ de log4j, getLogger() accepte un argument Class. Mais pour le reste, il n'y a aucun moyen de contourner cela si vous voulez que chaque classe ait un membre de journal statique avec sa propre catégorie.

+0

Autre moyen de contourner cela à part écrire un équivalent de getLogger qui prend une classe et appelle getName dessus? –

+0

Vous n'écrivez pas un équivalent, vous utilisez la méthode log4j org.apache.log4j.Logger # getLogger (Class clazz) qui existe depuis la version 1.2 de log4j. –

0

Vous pouvez raccourcir un tout petit peu, car getLogger est surchargé pour simplement prendre la classe. Comme si:

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

Le Logger peut être aussi fleixble ou inflexible que vous le souhaitez. Vous pouvez saisir un nouvel enregistreur pour chaque classe, comme dans l'exemple ci-dessus, et avoir une hiérarchie d'enregistreurs où vous pouvez contrôler et activer/désactiver la journalisation par classe. Ou si votre projet est petit ou un prototype, etc, vous pouvez simplement appeler Logger.getRootLogger() - mais vous perdrez la flexibilité d'affiner ce que vous consignez et ne consignez pas. Vous pourriez avoir une classe de base où la vie de l'enregistreur, et que tout le monde appelle celui-là, mais encore une fois, vous perdez une certaine flexibilité:

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

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

En bout de ligne, si vous voulez garder la possibilité d'affiner configurer l'enregistrement plus tard dans le projet (activer le débogage de niveau plus fin pour une seule classe), alors vous devrez peut-être coller avec le passe-partout dans chaque classe.

+0

votre classe de base utilise la mauvaise classe pour créer l'enregistreur. Mais, si vous l'avez corrigé, la sous-classe ne se connecterait-elle pas à l'enregistreur de la superclasse? – davetron5000

-1

Si vous faites l'enregistreur non statique, vous pouvez au moins hériter:

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

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

Voilà comment je l'ai toujours fait.

+0

Est-ce que cela n'enregistre pas tous les messages sur SomeBaseClass? –

+0

Non, getClass() renverra la classe d'exécution d'un objet –

+3

Mais le code de la classe parent/superclasse se connectera à l'enregistreur de la sous-classe. –

2

Si vous optez pour des enregistreurs de niveau package, avec l'ajout d'une classe de texte standard par paquet, vous pouvez écrire:

private static final Logger log = Logs.log; 

Il y a hacks de lire le nom de la classe de l'appelant (en fait l'enregistrement l'implémentation a un hack pour détecter la méthode actuelle), mais je ne le recommanderais pas.

3

En fonction de vos besoins d'exploitation, vous pouvez créer un « LoggingService » classe avec des méthodes statiques pour se connecter à différents « canaux ». J'ai constaté que je n'ai vraiment pas besoin de consigner la granularité au niveau de la classe. Vous pouvez nommer vos enregistreurs ce qui fonctionne le mieux pour vous. Nous l'utilisons dans de grandes applications d'entreprise depuis plusieurs années et la granularité n'a vraiment pas été un problème pour nous.

Le service d'enregistrement initialisé dans un bloc d'initialisation statique ... pour ainsi enregistrer un message:

LoggingService.logError ("bla");

Aucun code standard dans chaque classe.

Voici un service de journalisation exemple:

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

Je suppose que cela pourrait fonctionner pour vos besoins, mais personnellement je ne pense pas que le code client aurait besoin de savoir si le journal xml est activé ou si le journal dataAccess est activé. Ça ne me semble pas être une bonne interface. Et pourquoi avez-vous besoin d'enregistreurs séparés pour chaque niveau? A chacun son sien, je suppose. –

3

En fait, la pratique courante d'utiliser les noms de classe pour les noms de l'enregistreur est paresseux plus que tout.

La meilleure pratique consiste à nommer les enregistreurs selon le contexte de la tâche. Cela implique un peu plus de processus de réflexion et de planification, mais à la fin, le résultat est une granularité beaucoup plus significative, où vous pouvez basculer les niveaux de journalisation pour des tâches réelles plutôt que des classes.

+0

C'est un bon point. Bien que du point de vue d'un développeur, la consignation du nom de classe réel est plus facile à utiliser pour le débogage. Lorsque déployé à la production et surveillé, je pense que votre suggestion est la meilleure voie à suivre. –

+2

La connexion au nom de classe est une norme de facto pour la journalisation au niveau technique. L'utilisation du contexte logique est correcte, mais je l'associe davantage à la journalisation en tant qu'exigence métier, c'est-à-dire quelque chose comme l'audit. –

1

Vous pouvez réduire cela et beaucoup d'autres codes avec passe-partout lombok

https://github.com/rzwitserloot/lombok

@Slf4j 
    public class LogExample { 
} 

sera

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