Log4j源码分析及配置拓展
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;
public class ExtDOMConfigurator extends DOMConfigurator{
static public void configure(URL url) throws FactoryConfigurationError {
new ExtDOMConfigurator().doConfigure(url, LogManager. getLoggerRepository ());
}
@Override
public void parseLevel(Element element, Logger logger, boolean isRoot) {
if (element.getAttribute( "value" ).contains( "level" )) {
element.setAttribute( "value" , "info" );
}
}
@Override
protected void 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;
public class Log4jTest {
public static void 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" );
}
}
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息