深入Log4J源码之LoggerRepository和Configurator(五)

2014-11-24 08:39:23 · 作者: · 浏览: 2
p.get(c);
16 if (r != null) {
17 return r;
18 } else {
19 Class[] ia = c.getInterfaces();
20 for (int i = 0; i < ia.length; i++) {
21 r = searchInterfaces(ia[i]);
22 if (r != null)
23 return r;
24 }
25 }
26 return null;
27 }
28 public ObjectRenderer getDefaultRenderer() {
29 return defaultRenderer;
30 }
31 public void put(Class clazz, ObjectRenderer or) {
32 map.put(clazz, or);
33 }
ThrowableRendererSupport接口
ThrowableRendererSupport接口用于支持设置和获取ThrowableRenderer,从而用户可以自定义对Throwable对象的渲染。

1 public interface ThrowableRendererSupport {
2 ThrowableRenderer getThrowableRenderer();
3 void setThrowableRenderer(ThrowableRenderer renderer);
4 }
Hierarchy类以属性的方式实现了该接口,因而每个Hierarchy实例只能有一个全局的ThrowableRenderer,而不能像ObjectRender那样为不同的类定义不同的render。当时这种设计也是合理的,因为对Throwable的渲染最主要的就是其栈的渲染,其他的没什么大的不同,而且对栈渲染方式保持相同的格式会比较好。

1 private ThrowableRenderer throwableRenderer = null;
2 public Hierarchy(Logger root) {
3
4 defaultFactory = new DefaultCategoryFactory();
5
6 }
7 public void setThrowableRenderer(final ThrowableRenderer renderer) {
8 throwableRenderer = renderer;
9 }
10 public ThrowableRenderer getThrowableRenderer() {
11 return throwableRenderer;
12 }
Configurator接口

Configurator接口用于定义对配置文件的解析。在Log4J中配置文件解析出来的所有信息都可以放在LoggerRepository中,因而Configurator接口的定义非常简单。

1 public interface Configurator {
2 public static final String INHERITED = "inherited";
3 public static final String NULL = "null";
4 void doConfigure(URL url, LoggerRepository repository);
5 }
Log4J支持两种文件形式的配置文件:properties文件和xml文件,他们风别对应PropertyConfigurator类和DOMConfigurator类。

PropertyConfigurator类
PropertyConfigurator类解析properties文件的中的配置信息,可以设置log4j.debug为true以打开Log4J内部的日志信息;另外PropertyConfigurator还支持Linux风格的变量,即所有${variable}形式的变量都会被系统中对应的属性或配置文件内部定义的属性替换(先查找系统中的属性,后查找配置文件内部定义的属性);但是PropertyConfigurator不支持一些Log4J中的高级功能,如自定义ErrorHandler和定义AsyncAppender等。

Configurator中最重要的方法是doConfigure()方法,在PropertyConfigurator实现中,首先将配置文件对应的URL读取成Properties对象:

1 public void doConfigure(java.net.URL configURL, LoggerRepository hierarchy) {
2 Properties props = new Properties();
3
4 uConn = configURL.openConnection();
5 uConn.setUseCaches(false);
6 istream = uConn.getInputStream();
7 props.load(istream);
8
9 doConfigure(props, hierarchy);
10 }
而后检查是否设置了log4j.debug、log4j.reset、log4j.threshold等属性,如果有则做相应的设置。这里通过OptionConverter.findAndSubst()方法实现属性的查找和变量信息的替换。

1 public void doConfigure(Properties properties, LoggerRepository hierarchy) {
2 repository = hierarchy;
3 String value = properties.getProperty(LogLog.DEBUG_KEY);
4 if (value == null) {
5 value = properties.getProperty("log4j.configDebug");
6 if (value != null)
7 LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
8 }
9 if (value != null) {
10 LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
11 }
12 String reset = properties.getProperty(RESET_KEY);
13 if (reset != null && OptionConverter.toBoolean(reset, false)) {
14 hierarchy.resetConfiguration();
15 }
16 String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PRE