刚加入新公司,对日志的要求比较严格,对此特意花了几天时间看了一下log4j的源码,大概了解了一下log4j的实现方式,总结如下:
log4j的实现分为两个步骤:log4j.xml的加载,logger的使用
这里主要有两个问题,第一个问题是log4j.xml里的配置信息是怎样被logger使用的;第二个问题是logger的写文件是怎样控制的。
第一个问题
定义一个logger会这样使用
Logger logger = LogManager.getLogger("test");
依次进入getLogger
/**
Retrieve the appropriate {@link Logger} instance.
*/
public
static
Logger getLogger(final String name) {
// Delegate the actual manufacturing of the logger to the logger repository.
return getLoggerRepository().getLogger(name);
}
这里有两个方法,getLoggerReposityory()和getLogger(),先进入getLoggerRepository
static
public
LoggerRepository getLoggerRepository() {
if (repositorySelector == null) {
repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
guard = null;
Exception ex = new IllegalStateException("Class invariant violation");
String msg =
"log4j called after unloading, see http://logging.apache.org/log4j/1.2/faq.html#unload.";
if (isLikelySafeScenario(ex)) {
LogLog.debug(msg, ex);
} else {
LogLog.error(msg, ex);
}
}
return repositorySelector.getLoggerRepository();
}
这里repositorySelector是关键,最后返回LoggerRepository,repositorySelector是什么呢?是LogManager类下定义的一个静态变量
static private RepositorySelector repositorySelector;
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);
...
加载配置文件的源代码如下
/**
A static version of {@link #doConfigure(String, LoggerRepository)}. */
static
public
void configure(String filename) throws FactoryConfigurationError {
new DOMConfigurator().doConfigure(filename,
LogManager.getLoggerRepository());
}
是通过LogManager.getLoggerRepository()来加载的,由此解释第一个问题。
第二个问题,logger的写文件是怎样控制的
这个源代码有点多,简单解释一下,是通过解析log4j.xml或者log4j.property文件,通过反射的方式生成一个一个appender,然后加入到logger维护的一个列表下,当调用info,dubug,error,warn时通过调过遍历appender来实现对输入文件的控制
注:看得源码是针对log4j的1.0版本,估计2.0的版本也差不多
大致看懂了原理,自我标注一下,便于提高