Log4j源碼分析及配置拓展

jopen 12年前發布 | 38K 次閱讀 日志處理 log4j

Log4jjava中非常廣泛的日志記錄組件,使用非常簡單。在工程中加入Log4jjar包后,再加上簡單的Log4j.xml或者Log4j.properties等配置文件后就可以使用。其背后的實現原理是什么呢?假如我們的項目很大,各個配置文件的屬性需要寫在一個文件中,這樣便于實施人員修改。那該怎么辦?

先來討論Log4j實例化原理。使用Logger logger = Logger.getLogger(Log4jTest.class)能獲得Logger的實例。進入getLogger方法(在eclipse中按住Ctrl鍵后左鍵單擊方法名),可以看見Logger實例實例是由LogManager來創建的,它會讀取Log4j.xml或者Log4j.properties等配置文件,其配置文件中的屬性又是誰去讀的呢,進一步跟蹤,在OptionConverter.class類中selectAndConfigure方法中可以看到如下代碼:

if(clazz == null && filename != null && filename.endsWith(".xml")) {

     clazz = "org.apache.log4j.xml.DOMConfigurator";

   }

 

   if(clazz != null) {

     LogLog.debug("Preferred configurator class: " + clazz);

     configurator = (Configurator) instantiateByClassName(clazz,

                      Configurator.class,

                      null);

     if(configurator == null) {

     LogLog.error("Could not instantiate configurator ["+clazz+"].");

     return;

     }

   } else {

     configurator = new PropertyConfigurator();

   }

 

表示其配置類是由org.apache.log4j.xml.DOMConfigurator來實現的,我們也可以在系統變量中設置。DOMConfigurator類中定義了很多常量,用來表示Log4j.xml等配置文件的各個屬性。

現在我們假設項目中的Log4j.xml中的配置文件是下面這樣的。

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

 

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/

    <appender name="DailyRollingFileAppender" class="org.apache.log4j.DailyRollingFileAppender">

       <param name="File" value="${file}" />

       <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />

       <layout class="org.apache.log4j.PatternLayout">

           <param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{1}.%M(%L) - %m%n" />

       </layout>

    </appender>

    <root>

       <level value="${level}" />

       <appender-ref ref="CONSOLE" />

       <appender-ref ref="DailyRollingFileAppender"/>

    </root>

 

</log4j:configuration>

 

可以看到有兩條紅線選中的代碼,其中Filelevel并沒有直接賦值,這兩個值需要從項目中總的配置文件中讀取,其他開源組件的配置文件中經常修改的屬性也寫在這個總的配置文件中,這樣不僅僅是對開發人員,還對實施人員都方便多了。那么如何實現這個需求呢?

只需寫一個拓展類,繼承自DOMConfigurator.class,重寫其中的某些方法,并設置系統變量log4j.configuratorClass繼承自DOMConfigurator.class的拓展類,代碼如下:

拓展類:parseLevelsetParameter方法中的邏輯代碼可以自行處理。

package com.lsc.config;

publicclass ExtDOMConfigurator extends DOMConfigurator{

  

    staticpublicvoid configure(URL url) throws FactoryConfigurationError {

       new ExtDOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());

     }

    

   @Override

   publicvoid parseLevel(Element element, Logger logger, boolean isRoot) {

 

      if (element.getAttribute("value").contains("level")) {

        element.setAttribute("value", "info");

      }    

   }

 

   @Override

   protectedvoid setParameter(Element elem, PropertySetter propSetter) {

         if (elem.getAttribute("value").contains("f")) {

        elem.setAttribute("value", "E:/bizfuse/log/bizfuse.log");

      }

      super.setParameter(elem, propSetter);

   }

 

}

 

測試類:

package com.lsc;

publicclass Log4jTest {

 

   publicstaticvoid main(String[] args) {

      URL url = Log4j.class.getResource("/log4j.xml");

      System.setProperty("log4j.configuratorClass", "com.lsc.config.ExtDOMConfigurator");

      ExtDOMConfigurator.configure(url);

      Logger logger = Logger.getLogger(Log4jTest.class);

      logger.info(new Date() + "   test");

   }

 

}

轉自:http://www.cnblogs.com/lsc183/archive/2012/09/05/2672304.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!