2016-08-01 9 views
1

Ich habe ein Befehlszeilentool (frontend.java), das eine args4j-Optionsklasse (Options.java) und eine JUL-Konfigurationsklasse (LogConfig.java) verwendet. Da ich in meiner tatsächlichen Anwendung die ausgewählten Optionen sehen und verwenden muss, um die Protokollierung zu konfigurieren, habe ich in frontend einen statischen Getter, der die verschiedenen args4j-Optionen zurückgibt, die vom Benutzer ausgewählt wurden.Wie (und warum) sollte eine JUL-Konfigurationsklasse initialisiert werden?

frontend.java: 
import java.util.logging.Logger; 

public class frontend{ 
    private static Logger log = Logger.getLogger(frontend.class.getName()); 
    private static Options opts = new Options(); 

    public frontend(){ 
     System.out.println("Made a new front end"); 
    } 
    public static Options getOptions(){ 
     if(opts == null) 
      System.out.println("Opts was null"); 
     else 
      System.out.println("Opts is not null"); 
     return opts; 

    } 
    public static void main(String[] args) { 
     frontend fe = new frontend(); 
    } 
} 

Offensichtlich ist diese nächste Datei ist nicht wirklich leer, aber ich bin nicht sicher, dass ich irgendetwas müssen hier zeigen, was mein Problem ist.

Options.java: 
public class Options{ 
} 

Und schließlich die Konfigurationsklasse:

LogConfig.java: 
import java.util.logging.LogManager; 
import java.util.logging.Logger; 

import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

public class LogConfig { 
    public LogConfig() { 
     Options opts = frontend.getOptions(); 
     try { 
      LogManager.getLogManager().readConfiguration(new FileInputStream("logging.properties")); 
     }catch (SecurityException e) { 
      System.err.println("Problem accessing log config file: " 
           + e.getMessage()); 
     } catch (IOException e) { 
      System.err.println("Problem loading log config file: " 
           + e.getMessage()); 
     } 
    } 
} 

Mein Problem ist, dass die LogConfig Klasse einen Halt des opts Variable zu bekommen scheint, bevor es durch die statische Initialisierung gesetzt worden ist:

Output: 
c:\>java -cp . frontend 
Made a new front end 
Opts is not null 

c:\>java -Djava.util.logging.config.class=LogConfig -cp . frontend 
Opts was null 
Made a new front end 
Opts is not null 

c:\> 

Was ist der beste Ansatz für die Verwendung der JUL-Protokollkonfigurationsklasse, wenn Ihre Hauptklasse etwas lebendig sein muss, bevor Sie wissen, was Ihr Conf ist ignation Klasse muss durchgeführt werden?

Antwort

1

Das Erstellen des Loggers löst den LogManager-Start aus. Verzögern Sie die Erstellung Ihres Loggers, bis Sie ihn verwenden müssen.

public class frontend { 

    private static volatile Logger log; 
    private static Options opts = new Options(); 

    public frontend() { 
     System.out.println("Made a new front end"); 
    } 

    public static Options getOptions() { 
     if (opts == null) { 
      System.out.println("Opts was null"); 
     } else { 
      System.out.println("Opts is not null"); 
     } 
     return opts; 

    } 

    public static void main(String[] args) { 
     frontend fe = new frontend(); 
     log = Logger.getLogger(frontend.class.getName()); 
    } 
} 

Ansonsten können Sie einfach die selbst Config-Klasse neu erstellen, nachdem der LogManager Startvorgang abgeschlossen ist. Dann machen Sie Ihre LogConfig einen No-Op ausführen, wenn die getOptions Null zurückgibt.

public class frontend { 

    private static final Logger log = Logger.getLogger(frontend.class.getName()); 
    private static Options opts = new Options(); 

    public frontend() { 
     System.out.println("Made a new front end"); 
    } 

    public static Options getOptions() { 
     if (opts == null) { 
      System.out.println("Opts was null"); 
     } else { 
      System.out.println("Opts is not null"); 
     } 
     return opts; 

    } 

    public static void main(String[] args) { 
     frontend fe = new frontend(); 
     init(); 
    } 

    private static void init() { 
     String n = System.getProperty("java.util.logging.config.class"); 
     if (n != null) { 
      try { //LogManager uses the system class loader. 
       Class<?> k = Class.forName(n, false, 
         ClassLoader.getSystemClassLoader()); 
       k.newInstance(); 
      } catch (ReflectiveOperationException | LinkageError ignore) { 
       ignore.printStackTrace(); 
      } 
     } 
    } 
} 
+0

Danke, das ist eigentlich, was ich getan habe - nämlich, die Log-Konfiguration in die Initialisierung von 'Frontend' zu setzen. Es scheint mir, dass dies in vielen Fällen den Begriff "java.util.logging.config.class" sowie die globale "config" -Eigenschaft überflüssig macht. Was Sie hier haben (und was ich getan habe), scheint mir, die "freie" Konfigurationsverarbeitung zu umgehen. Anstatt entweder den OOTB- "java.util.logging.config.class" -Mechanismus oder die Introspektion zu verwenden, habe ich einfach getan, was LogConfig.configure() entspricht. Ich denke, der Haken ist, dass die Konfigurationsklasse nicht in die Frontend-Klasse eingeweiht werden kann. – AndyJ

Verwandte Themen