Javaで開発してるとlog4jの恩恵を受ける日々を送っています。log4j.xmlをクラスパス上に配置すると勝手に読み込んでくれるので、その部分の機能を確認してみようと。
まずは結論から入り、その後にソースコードの解析を。
設定ファイル読み込み 優先順位(結論)
- 設定ファイル読み込みロジック
- 読み込む設定ファイルの優先順位
解析実施
- まずはソースファイルのDL
http://logging.apache.org/
上記、オフィシャルサイトに行って log4j のソースファイルを落としましょう。今回私が落としたファイルは「apache-log4j-1.2.15.zip」です。
- 設定ファイルの読み込み箇所を探す
どうせ決めうちだろうと妄想し、「log4j.xml」でソースプロジェクトを検索し、以下のコードを発見した。
package org.apache.log4j; (中略) public class LogManager { (中略) static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties"; static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml"; static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration"; static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass"; public static final String DEFAULT_INIT_OVERRIDE_KEY = "log4j.defaultInitOverride";
上記の変数「DEFAULT_XML_CONFIGURATION_FILE」を使用している部分をさらに検索する。
設定ファイルの読み込み部分は、「org.apache.log4j.LogManager」クラスのstaticフィールドを利用していた。
static { String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,null); if(override == null || "false".equalsIgnoreCase(override)) { String configurationOptionStr = OptionConverter.getSystemProperty(DEFAULT_CONFIGURATION_KEY, null); String configuratorClassName = OptionConverter.getSystemProperty(CONFIGURATOR_CLASS_KEY, null); URL url = null; if(configurationOptionStr == null) { url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE); if(url == null) { url = Loader.getResource(DEFAULT_CONFIGURATION_FILE); } }else{ try { url = new URL(configurationOptionStr); } catch (MalformedURLException ex) { url = Loader.getResource(configurationOptionStr); } } (中略) }
上記ソースコードを確認すると、クラスパス上 or システムプロパティ引数からのパスを指定してから log4j設定ファイルのパスを読み込んでいる。設定ファイルのパスを取得するため、それぞれ「Loader」、「OptionConverter」クラスを使用している。これら2クラスのコードで気になる部分だけ抜粋してみる。
//Thread.currentThread().getContextClassLoader().getResourceをしてるだけ static public URL getResource(String resource) { ClassLoader classLoader = null; URL url = null; try { if(!java1) { classLoader = getTCL(); if(classLoader != null) { url = classLoader.getResource(resource); (中略) } private static ClassLoader getTCL() throws IllegalAccessException, InvocationTargetException { Method method = null; try { method = Thread.class.getMethod("getContextClassLoader", null); } catch (NoSuchMethodException e) { return null; } return (ClassLoader) method.invoke(Thread.currentThread(), null); } (中略)
//どう見てもSystem.getPropertyにデリゲートしてるだけ。 String getSystemProperty(String key, String def) { try { return System.getProperty(key, def); (中略)