web-dev-qa-db-fra.com

Java Journalisation avec des classes abstraites

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?

51
shuniar

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.

90
Peter Lawrey

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

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.

5
AlexR

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.
    }
}
2
Shubham Mishra

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.

1
herrtim