Log4j.properties文件自動加載

org.apache.log4j.LogManager類有一個靜態塊,首先是找log4j.xml,找不到的情況下才找log4j.properties
Java code
static {
    // By default we use a DefaultRepositorySelector which always returns 'h'.
    Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
    repositorySelector = new DefaultRepositorySelector(h);

    /** Search for the properties file log4j.properties in the CLASSPATH.  */
    String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
                               null);

    // if there is no default init override, then get the resource
    // specified by the user or the default config file.
    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 the user has not specified the log4j.configuration
      // property, we search first for the file "log4j.xml" and then
      // "log4j.properties"
      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) {
      // so, resource is not a URL:
      // attempt to get the resource from the class path
      url = Loader.getResource(configurationOptionStr); 
    }    
      }
      
      // If we have a non-null url, then delegate the rest of the
      // configuration to the OptionConverter.selectAndConfigure
      // method.
      if(url != null) {
    LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");      
    OptionConverter.selectAndConfigure(url, configuratorClassName, 
                       LogManager.getLoggerRepository());
      } else {
    LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
      }
    }  
  }

換句話說,是什麼呢?也就是說:

1. 獲取系統屬性,看是否用戶設置了override。默認是不設置的。

2. 如果確實沒有設置,那麼嘗試找一下,有沒有log4j.xml,有則加載。

3. 如果還沒有,那麼嘗試找一下,有沒有log4j.properites,有則加載。

其中,2、3裏提到的“嘗試找一下”,可能是去哪個目錄裏面找呢?翻譯了一下,效果不好,還是上原文清晰 :

  1. Search for resource using the thread context class loader under Java2. If that fails, search for resource using the class loader that loaded this class (Loader). Under JDK 1.1, only the the class loader that loaded this class (Loader) is used.
  2. Try one last time with ClassLoader.getSystemResource(resource), that is is using the system class loader in JDK 1.2 and virtual machine's built-in class loader in JDK 1.1. 

 

所以,你把log4j.xml或log4j.properties放在這些目錄下,那麼log4j會“自動去加載”到,不用程序裏手工寫加載代碼了。



2,然後是怎麼找呢:如下代碼,是委託給classloader(加載Loader類的classloader)去找了,
Java code
// We could not find resource. Ler us now try with the // classloader that loaded this class. classLoader = Loader.class.getClassLoader(); if(classLoader != null) { LogLog.debug("Trying to find ["+resource+"] using "+classLoader +" class loader."); url = classLoader.getResource(resource); if(url != null) { return url; } }


3,classloader的getResource(...)又是怎麼找呢:總是先從父classloader裏去找,找不到才自己去找
Java code
public URL getResource(String name) { URL url; if (parent != null) { url = parent.getResource(name); } else { url = getBootstrapResource(name); } if (url == null) { url = findResource(name); } return url; }


總結:對於不同的應用服務器(或者web服務器)來說,classloader的層次不盡相同。這裏以最簡單的tomcat來說,如果你的應用是部署到tomcat下的,使用log4j配置文件的順序就是$TOMCAT_HOME/lib/log4j.xml或者log4j.properties==>你自己web應用/WEB-INF/classes(或者lib)/log4j.xml或者log4j.properties.
對於WEB-INF下是classes優先還是lib優先 你可以自己測試一下。

發佈了28 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章