Java Logging With Abstract Classes

Je travaille sur un projet, et je travaille actuellement à l’implémentation de la journalisation avec log4j et j’étais curieux de savoir comment procéder pour implémenter les journaux. Les deux implémentations dont je parle sont les suivantes:

Première option

Utilisez un seul journal de la super classe pour cette classe et toutes les sous-classes:

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

Deuxième option

Utilisez des journaux individuels pour chaque classe, super et sous-titres:

 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’est-ce qui a plus de sens et pourquoi?

Je ne ferais pas non plus. Au lieu de cela je le ferais utiliser la classe correcte dans les deux cas.

 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 vous ne faites pas beaucoup de consignation (ce qui est une bonne idée de toute façon), vous pouvez utiliser une méthode à la place.

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

Si une classe appelle cela beaucoup, vous pouvez la remplacer pour vous donner une instance mise en cache.

Ceci est ma solution (enregistreur statique 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"); } } 

Les deux ont du sens. Cela dépend de votre application.

Je pense que la pratique la plus souvent utilisée est d’avoir un enregistreur privé pour chaque classe. Cela vous permet de configurer la journalisation à la fois par classe et par package. Rappelez-vous que AbstractFoo et Foo peuvent appartenir à différents paquets et que vous voulez probablement voir uniquement les journaux de Foo .

De plus, réfléchissez toujours à deux fois si vous voulez écrire protected champ protected . Ce n’est pas complètement interdit mais une mauvaise pratique bien connue. Cela rend votre code moins lisible et difficile à gérer.

Si vous créez le journal dans la classe abstraite, les journaux seront tous étiquetés comme provenant de AbstractFoo. Si vous voulez / devez voir les journaux marqués avec la classe enfant à partir de laquelle le journal s’est produit, créez des journaux pour les classes enfants.

La même chose peut être obtenue en jouant avec les constructeurs. Ajoutez un enregistreur au niveau de la classe de base et définissez-le à partir de chaque classe dérivée à l’ aide de super (). Il y a le code:

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