2012-08-28 25 views
35

Pracuję nad projektem i obecnie pracuję nad implementacją niektórych logów z log4j i byłem ciekawy, jak powinienem wdrożyć dzienniki. Obie implementacje jestem kopanie wokół są następujące:Java Logging With Abstract Classes

Pierwsza opcja

Zastosowanie pojedynczego dziennika z super klasy dla tej klasy i wszystkie klasy podrzędne:

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

Druga opcja

Stosuj indywidualne dzienniki dla każdej klasy, super i sub:

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

Co ma większy sens i dlaczego?

Odpowiedz

58

Ja też bym nie zrobił. Zamiast tego sprawiłbym, że użyłaby odpowiedniej klasy w obu przypadkach.

public abstract class AbstractFoo { 
    protected final Log log = LogFactory.getLog(getClass()); 

    ... 
} 

public class Foo extends AbstractFoo { 
    public void someMethod() { 
     log.info("Using abstract log"); 
    } 
} 

Jeśli nie robisz dużo rejestrowania (i tak jest dobry pomysł), możesz zamiast tego użyć metody.

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

    ... 
} 

Jeśli istnieje klasa, która nazywa to dużo, można ją przesłonić, aby uzyskać instancję z pamięci podręcznej.

+1

Do tej pory widziałem dwa podejścia: statyczne rejestratory (jak w pytaniu) i niestatyczne rejestratory (jak w twoim przykładzie). Czy statyczne rejestratory nie są lepszym rozwiązaniem (jedna instancja rejestratora dla wszystkich instancji)? –

+4

statyczne rejestratory są lepsze, jeśli są takie same dla wszystkich instancji. W przypadku klasy abstrakcyjnej klasa instancji nie jest taka sama. –

+0

Podoba mi się to, wydaje się dobrym sposobem na połączenie obu opcji.Kończy się jeden dziennik, ale wiąże się z odpowiednią klasą. +1 – shuniar

2

Oba mają sens. To zależy od twojej aplikacji.

Myślę, że częściej stosowaną praktyką jest posiadanie prywatnego rejestratora dla każdej klasy. Pozwala to skonfigurować logowanie zarówno w klasie, jak i w pakiecie. Pamiętaj, że AbstractFoo i Foo mogą należeć do różnych pakietów i prawdopodobnie chcesz zobaczyć tylko dzienniki z Foo.

Ponadto zawsze dwa razy pomyśleć, jeśli chcesz napisać pole protected. Nie jest to całkowicie zabronione, ale dobrze znana zła praktyka. Dzięki temu twój kod jest mniej czytelny i trudny do utrzymania.

1

Jeśli utworzysz program rejestrujący w klasie abstrakcyjnej, wszystkie dzienniki będą oznaczane jako pochodzące z AbstractFoo. Jeśli chcesz/potrzebujesz zobaczyć dzienniki otagowane klasą potomną, z której powstał log, utwórz rejestratory dla klas dzieci.

+0

"Jeśli utworzysz program rejestrujący w klasie abstrakcyjnej, wszystkie dzienniki zostaną oznaczone jako pochodzące z AbstractFoo" -> Nie, nie jest to prawdą, jeśli używasz Zaakceptowanej odpowiedzi przez @Peter_Lawrey. Następnie otrzymujesz dzienniki oznaczone jako klasa, wykonując rejestrowanie, zawsze. – cellepo

+0

"Problem" z odpowiedzią Lawrey'a polega na tym, że teraz są to rejestry oparte na instancjach, co nie jest pomysłem. – MeBigFatGuy

5

To jest moje rozwiązanie (końcowe rejestratora statyczny):

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

To samo można osiągnąć grając z konstruktorów. Dodaj rejestrator na poziomie klasy i ustaw go z każdej klasy za pomocą super(). Jest kod:

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