LogManager
1 field : 常量和RepositorySelector
2 静态代码块
- 创建默认的日志容器 Hierarchy
- 创建默认的容器选择器 RepositorySelector
- 判断加载的配置文件
首先来加载xml文件,然后加载properties文件,构建为URL对象。
调用方法来加载文件,configuratorClassName为配置的读取文件类,后面那个是容器。
OptionConverter.selectAndConfigure(url, configuratorClassName, LogManager.getLoggerRepository());
<span style="font-size:14px;">static public void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {// 配置文件地址,指定解析类,容器
Configurator configurator = null;
String filename = url.getFile();
if (clazz == null && filename != null && filename.endsWith(".xml")) { //如果是xml文件,且没有指定解析类
clazz = "org.apache.log4j.xml.DOMConfigurator"; // 默认指定xml解析类
}
if (clazz != null) {
LogLog.debug("Preferred configurator class: " + clazz);
configurator = (Configurator) instantiateByClassName(clazz, Configurator.class, null); // 实例化clazz
if (configurator == null) {
LogLog.error("Could not instantiate configurator [" + clazz + "].");
return;
}
} else {
configurator = new PropertyConfigurator(); // 没有解析类 ,则用 property
}
configurator.doConfigure(url, hierarchy); // 加载配置
}</span>
插入 实例化clazz的过程 Class.forName(clazz) 或者 log4j用反射等同Thread.currentThread().getContextClassLoader().loadClass(clazz)
下面说明属性文件加载过程
doConfigure有四个重载方法,最终调用doConfigure(Properties,LoggerRepository)
先判断了一个log4j.debug属性,默认开启内部日志debug模式
LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true)); // 默认允许
然后判断log4j.reset属性,当且仅当false时,容器重配resetConfiguration()
最后log4j.threshold属性,会解析值,如果值包含${} 变量或者 ${${}} 这种情况,
解析的value可能格式为levle#classname形式,可自定义设置threshold
<ol><li><span style="font-family: Arial, Helvetica, sans-serif;"> configureRootCategory(properties, hierarchy); // 配置 root logger</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"> configureLoggerFactory(properties); // 配置 logfactory</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"> parseCatsAndRenderers(properties, hierarchy); // 解析 logger 和 渲染</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"> LogLog.debug("Finished configuring.");</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"> registry.clear(); // 不持有appenders引用,gc回收</span></li></ol>
第一步
解析log4j.rootlogger属性,如果不是空字符串且不以逗号开头,得到levelStr,如果levelStr等同于inherited或者null,判断是否为root来设置level
然后清空logger的appender,在解析配置中的appender,添加到logger中。
用hashtable来判断是否已加载过appender
三个属性,后两个要判断appender instanceof OptionHandler
log4j.appender.appenderName log4j.appender.appenderName.layout log4j.appender.appederName.errorHandler
layout 除了实例化外 增加PropertySetter.setProperties操作
errorhandler 增加解析ref操作和PropertySetter.setProperties操作
解析Filters,log4j.appender.appenderName.filter
PropertySetter.setProperties(); 稍后说明,大意是通过配置获取属性和value,然后通过反射来赋值。
第二步
读取配置的log4j.loggerfactory 实例、属性赋值
第三步
1 解析logger 解析过程同第一步,增加 log4j.additivity的设置
2 renderer
RendererMap.
addRenderer稍后说明
3 throwablerenderer
另外PropertyConfigurator提供configureAndWatch方法来检查配置的更改。
PropertyWatchDog extends FileWatchDog 重写父类 doOnchange(),由父类调用,模板方法