Je travaille sur un projet, et je travaille actuellement sur l'implémentation d'une journalisation avec log4j et j'étais curieux de savoir comment je devrais procéder pour implémenter les journaux. Les deux implémentations que je lance sont les suivantes:
Première option
Utilisez un seul journal de 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-marins:
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?
Moi non plus. Au lieu de cela, je lui ferais utiliser la bonne classe 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 journalisation (ce qui est de toute façon une bonne idée), vous pouvez utiliser une méthode à la place.
public abstract class AbstractFoo {
protected Log log() { return LogFactory.getLog(getClass()); }
...
}
S'il existe une classe qui appelle beaucoup cela, vous pouvez la remplacer pour vous donner une instance mise en cache.
Voici ma solution (enregistreur statique final):
public abstract class AbstractFoo {
protected abstract 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 par classe et par package. N'oubliez pas que AbstractFoo
et Foo
peuvent appartenir à des packages différents et que vous souhaitez probablement voir uniquement les journaux de Foo
.
De plus, réfléchissez toujours à deux fois si vous voulez écrire le champ protected
. Ce n'est pas complètement interdit mais c'est une mauvaise pratique bien connue. Cela rend votre code moins lisible et difficile à maintenir.
La même chose peut être obtenue en jouant avec les constructeurs. Ajoutez un enregistreur au niveau de la classe Base et définissez-le à partir de chaque ( Dérivée classe utilisant 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.
}
}
Si vous créez l'enregistreur dans la classe abstraite, les journaux seront tous étiquetés comme provenant de AbstractFoo. Si vous souhaitez/devez voir les journaux balisés avec la classe enfant à partir de laquelle le journal s'est produit, créez des consignateurs pour les classes enfants.