2013-03-15 9 views
10

Ich habe eine Unterklasse und eine Oberklasse. In der Oberklasse habe ich eine Methode, die etwas protokolliert. Wenn ich eine Instanz der Unterklasse erstelle, erstellt der Logger eine Protokollierungsnachricht für die Superklasse. Warum passiert dies?Wie bekomme ich einen Logger für eine Unterklasse?

Code-Beispiel:

SuperClass.java

import java.util.logging.Level; 
import java.util.logging.Logger; 

public abstract class SuperClass { 
    public void logAndPrintClass(){ 
     String name = this.getClass().getName(); 
     System.out.println(name); 
     Logger logger = Logger.getLogger(name); 
     logger.log(Level.INFO, "Logmessage"); 
    } 
} 

SubClass.java

public class SubClass extends SuperClass { 
} 

TestLogBubClass.java

public class TestLogBubClass { 

    public static void main(String[] args){ 
     SuperClass obj = new SubClass(); 
     obj.logAndPrintClass(); 
    } 
} 

Ausgang:

SubClass 
Mar 15, 2013 6:30:04 PM SuperClass logAndPrintClass 
INFO: Logmessage 

Wie Sie sehen, ist der Name der Klasse korrekt gedruckt, aber in der Protokollnachricht falsch dargestellt.

Antwort

5

Dieser Grund ist in der JavaDoc für LogRecord:

Beachten Sie, dass, wenn die Client-Anwendung einen expliziten Quelle Methodennamen und Quellklassennamen nicht angegeben hat, dann ist die LogRecord Klasse sie automatisch geschlossen werden, wenn sie zum ersten Mal sind Zugriff (aufgrund eines Aufrufs von getSourceMethodName oder getSourceClassName) durch Analysieren des Aufruf-Stacks.

die Aufrufliste in diesem Fall endet an einem Verfahren, durch SuperClass definiert, so dass die LogRecord annimmt, dass es die Klasse aufgerufen wird. Wenn Sie diese in Aktion sehen möchten, führen Sie diesen Code:

public class Example { 

    public static class Superclass { 
     public void foo() { 
      new Exception().printStackTrace(); 
     } 
    } 

    public static class Subclass extends Superclass { 
     // nothing here 
    } 

    public static void main(String[] argv) 
    throws Exception 
    { 
     Superclass s = new Subclass(); 
     s.foo(); 
    } 
} 

Edit: Ich benutze Juli nicht, aber hatte gehofft, dass es eine einfache Möglichkeit, um die Ausgabe zu konfigurieren (wie jeder andere Logger Implementierung bietet). Es scheint, dass Sie Ihre eigene Formatter-Klasse implementieren müssen, und geben Sie sie unter Verwendung der java.util.logging.ConsoleHandler.formatter-Eigenschaft an.

Ich würde empfehlen, wenn möglich auf SLF4J zu wechseln. Sie können alle bestehenden j.u.l Code durch SLF4J zu einem tatsächlichen Logger, der Ihnen mehr Kontrolle über seine Ausgabe gibt (wie Log4J oder Logback).

0

Ich denke, ich habe einen Workaround, auch wenn ich keine vollständige Erklärung liefern kann.

die logAndPrintClass mit nur einem super Anruf, wie diese Aufschalten, in SubClass:

class SubClass extends SuperClass { 
    protected void logAndPrintClass(){ super.logAndPrintClass(); } 
} 

Ich habe immer noch die gleiche Leistung.

SubClass 
Mar 15, 2013 11:22:10 AM SuperClass logAndPrintClass 
INFO: Logmessage 

Dann kopierte ich einfach die Methode Körper in die Unterklasse:

class SubClass extends SuperClass { 
    protected void logAndPrintClass(){ 
     String name = this.getClass().getName(); 
     System.out.println(name); 
     Logger logger = Logger.getLogger(name); 
     logger.log(Level.INFO, "Logmessage"); 
    } 
} 

Dann habe ich verschiedene Ausgabe:

SubClass 
Mar 15, 2013 11:23:31 AM SubClass logAndPrintClass 

Ich weiß nicht, warum das funktioniert, aber die einzige Unterschied Ich finde zu finden ist, dass das Logger Objekt wird nun innerhalb der Unterklasse statt innerhalb der Oberklasse instanziiert.

+0

Es ist eigentlich, dass das LogRecord-Objekt, das hinter dem Aufruf von logger.log() versteckt ist, in der Unterklasse erstellt wird. – parsifal

+0

Ich möchte nicht die Methode in jeder Unterklasse aus Gründen der Protokollierung überschreiben. Im Produktionscode kann mehr als nur eine Nachricht gedruckt und protokolliert werden. Der Code in der Frage ist nur das einfachste Beispiel mit dem gleichen Verhalten. – Paling

1

Dieser java.util.logging Code ist ziemlich seltsam .. Die Protokollierung verwendet nicht die name, sondern versucht, die Quellklasse selbst herauszufinden (die dann protokolliert wird). Schauen Sie sich die Methode private void inferCaller() in der Klasse an.

1

@Parsifal erklärte, warum dies passiert, werde ich versuchen, eine Problemumgehung zu erklären. Wenn Sie die genaue Klasse sehen möchten, wo die Methode aufgerufen wird, würde ich empfehlen, log4j oder slf4j zu verwenden. Wenn Sie java.util.Logger verwenden müssen, sehen Sie sich bitte jul-to-slf4j an.

ich versucht habe und für mich mit den gleichen Klassen Eingang wie die folgenden in meinem Standardausgabe aussieht:

SubClass

15. März 2013 08.39.44 Superclass logAndPrintClass

INFO:

LogMessage

20: 39: 44.478 INFO SubClass: 12 - LogMessage

nur

und in der Log-Datei befindet sich:

20: 39: 44.478 INFO SubClass: 12 - LogMessage

Es könnte aussehen nicht so gut, aber in einigen Fällen könnte dies sein als geeignete Problemumgehung.