java日志系统log4j配置解析过程,源码分析
log4j 可以看成是非常类似jdk logger 结构 ,有个logger 与logManger
都是在logManger的静态块中初始化类,加载配置文件
Logger.getLogger(Test.class);
1
从getLogger开始,就启动了log4j的整个工作流程,通过调用LogManager获取logger实例
return LogManager.getLogger(clazz.getName());
1
LogManager类里面有个静态块static{},【初始化尝试读取配置文件】先尝试加载log4j.xml [DEFAULT_XML_CONFIGURATION_FILE] ,再尝试log4j.properties [DEFAULT_CONFIGURATION_FILE]
url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
if(url == null) {
url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
}
1
2
3
4
如果找到了配置文件,就会开始解析配置文件
//url是配置文件路径,LogManager.getLoggerRepository()是Hierarchy类
OptionConverter.selectAndConfigure(url, configuratorClassName,
LogManager.getLoggerRepository());
//继而开始调用
configurator = new PropertyConfigurator();
//加载properties配置文件
configurator.doConfigure(url, hierarchy);
//从这开始就解析所有配置信息的入口,可以设置断点,debug调试
doConfigure(props, hierarchy);
1
2
3
4
5
6
7
8
9
在doConfigure(props, hierarchy)方法里可以看到
1、添加java vm 启动参数 -Dlog4j.configDebug=true或-Dlog4j.debug=true可以打开Loglog的debug输出 (Loglog是log4j内部的输出调试类)
//配置文件中打开Loglog的输出,debug
String value = properties.getProperty(LogLog.DEBUG_KEY);
if(value == null) {
value = properties.getProperty("log4j.configDebug");
if(value != null)
LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
}
if(value != null) {
LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
}
1
2
3
4
5
6
7
8
9
10
11
2、一些配置,log4j.reset、log4j.threshold
String reset = properties.getProperty(RESET_KEY);
if (reset != null && OptionConverter.toBoolean(reset, false)) {
hierarchy.resetConfiguration();
}
String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX,
properties);
if(thresholdStr != null) {
hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr,
(Level) Level.ALL));
LogLog.debug("Hierarchy threshold set to ["+hierarchy.getThreshold()+"].");
}
1
2
3
4
5
6
7
8
9
10
11
12
3、配置root logger,LoggerFactory等等
configureRootCategory(properties, hierarchy);
configureLoggerFactory(properties);
1
2
PropertyConfigurator类是主要的配置解析类,OptionConverter类是转换值true到boolen,获取根据key从properties取值交给PropertyConfigurator解析。
LogManager的静态块主要是初始化自己(实例化repositorySelector,读取配置),【root logger默认debug】【Hierarchy 是loggerfactory,提供有层级的,父子关系的logger】
Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
1
LogManager.getLogger里面getLoggerRepository().getLogger(name);
就是通过Hierarchy.getLogger(name)取得logger实例
Hierarchy内部使用Hashtable ht 保存key为name的logger实例,单例模式,
1
2
3
这样就完成了获取logger
当调用logger记录日志时,默认是debug等级
logger.debug(“debug”);
logger.debug("debug");
触发
forcedLog(FQCN, Level.DEBUG, message, null);
callAppenders(new LoggingEvent(fqcn, this, level, message, t));
//writes 初始0, writes += c.aai.appendLoopOnAppenders(event);就是配置的appender(aai是AppenderAttachableImpl就是logger里保存定义的多个appender)
if(writes == 0) {
repository.emitNoAppenderWarning(this);//输出没有配置appender的警告
}
1
2
3
4
5
6
7
8
9
如果logger没有找到appender,就是具体的日志处理,就报错了,不执行,所以【log4j必须先配置再使用】
可以在main方法中 【BasicConfigurator.configure();】 快速初始化
log4j:WARN No appenders could be found for logger (Test).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
1
2
3
【一些主要方法的功能】
org.apache.log4j.PropertyConfigurator#configureRootCategory
解析配置文件中对root logger的配置 (log4j.rootLogger开头的配置)
org.apache.log4j.PropertyConfigurator#parseAdditivityForLogger
处理非root logger的additivity属性(默认为真,继承父logger的appenders)
org.apache.log4j.PropertyConfigurator#parseAppender
实例化配置中的appender(log4j.appender.开头 + appenderName)
org.apache.log4j.PropertyConfigurator#parseCategory
配置包括root logger的各个包内的logger (logger是Category的子类,表示各个不同包内的logger)
————————————————
以上是 java日志系统log4j配置解析过程,源码分析 的全部内容, 来源链接: utcz.com/z/512547.html