Log4j源碼分析及配置拓展
Log4j是java中非常廣泛的日志記錄組件,使用非常簡單。在工程中加入Log4j的jar包后,再加上簡單的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>
可以看到有兩條紅線選中的代碼,其中File和level并沒有直接賦值,這兩個值需要從項目中總的配置文件中讀取,其他開源組件的配置文件中經常修改的屬性也寫在這個總的配置文件中,這樣不僅僅是對開發人員,還對實施人員都方便多了。那么如何實現這個需求呢?
只需寫一個拓展類,繼承自DOMConfigurator.class類,重寫其中的某些方法,并設置系統變量log4j.configuratorClass為繼承自DOMConfigurator.class的拓展類,代碼如下:
拓展類:parseLevel和setParameter方法中的邏輯代碼可以自行處理。
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