在上一篇文章里,我们故意遗漏了一个重要的接口,AppenderAttachable:
public interface AppenderAttachable {
public void addAppender(Appender newAppender);
public Enumeration getAllAppenders();
public Appender getAppender(String name);
public boolean isAttached(Appender appender);
void removeAllAppenders();
void removeAppender(Appender appender);
void removeAppender(String name);
}
顾名思义,继承该接口的类可以attach Appenders, Category类继承了这个借口,因此也提供了相应的API。我们在配置文件里面设置的Appender属性会在配置类中被加载到Logger:Category对象中。
然而在Category类中,并没有真正的实现这些API,它将之代理到了其AppenderAttachableImpl变量中。回到第一篇文章中的类图,我们可以知道, AppenderAttachableImpl类同样也继承了AppenderAttachable接口。仔细一看,这里其实用了一个代理模式。
而在AppenderAttachableImpl中,维护了一个Appender类型列表,而Appender则是真正做事的人。。。
public int appendLoopOnAppenders(LoggingEvent event) {
int size = 0;
Appender appender;
if(appenderList != null) {
size = appenderList.size();
for(int i = 0; i < size; i++) {
appender = (Appender) appenderList.elementAt(i);
appender.doAppend(event);
}
}
return size;
}
所以,我们回来看第一章的序列图,并不完整,我们现在来将之补全:
后面我们会继续补全这张图片。
Appender的具体实现类并不直接继承Appender,而是继承于Appender的一个抽象实现:AppenderSkeleton,这个类维护了Filter以及Layout的实例,你可以在Log4j配置项中找到Filter以及Layout, 这里不再赘述。 我们常见的XMLAppender,或者HTMLAppender都是继承于该类。