深入Log4J源码之Log4J Core (九)

2014-11-24 08:26:37 · 作者: · 浏览: 6
this.layout = layout;
12 this.setWriter(writer);
13 }
14 public void append(LoggingEvent event) {
15 if (!checkEntryConditions()) {
16 return;
17 }
18 subAppend(event);
19 }
20 protected boolean checkEntryConditions() {
21 if (this.closed) {
22 LogLog.warn("Not allowed to write to a closed appender.");
23 return false;
24 }
25 if (this.qw == null) {
26 errorHandler
27 .error("No output stream or file set for the appender named ["
28 + name + "].");
29 return false;
30 }
31 if (this.layout == null) {
32 errorHandler.error("No layout set for the appender named [" + name
33 + "].");
34 return false;
35 }
36 return true;
37 }
38 protected void subAppend(LoggingEvent event) {
39 this.qw.write(this.layout.format(event));
40 if (layout.ignoresThrowable()) {
41 String[] s = event.getThrowableStrRep();
42 if (s != null) {
43 int len = s.length;
44 for (int i = 0; i < len; i++) {
45 this.qw.write(s[i]);
46 this.qw.write(Layout.LINE_SEP);
47 }
48 }
49 }
50 if (shouldFlush(event)) {
51 this.qw.flush();
52 }
53 }
54 public boolean requiresLayout() {
55 return true;
56 }
57 }
ConsoleAppender继承自WriterAppender,它只是简单的将System.out或System.err实例传递给WriterAppender以构建相应的writer,最后实现将日志写入到控制台中。

Filter类
在Log4J中,Filter组成一条链,它定了以decide()方法,由子类实现,若返回DENY则日志不会被记录、NEUTRAL则继续检查下一个Filter实例、ACCEPT则Filter通过,继续执行后面的写日志操作。使用Filter可以为Appender加入一些出了threshold以外的其他逻辑,由于它本身是链状的,而且它的执行是横跨在Appender的doAppend方法中,因而这也是一个典型的AOP的概念。

1 public abstract class Filter implements OptionHandler {
2 public Filter next;
3 public static final int DENY = -1;
4 public static final int NEUTRAL = 0;
5 public static final int ACCEPT = 1;
6 public void activateOptions() {
7 }
8 abstract public int decide(LoggingEvent event);
9 public void setNext(Filter next) {
10 this.next = next;
11 }
12 public Filter getNext() {
13 return next;
14 }
15 }
Log4J本身提供了四个Filter:DenyAllFilter、LevelMatchFilter、LevelRangeFilter、StringMatchFilter。

DenyAllFilter只是简单的在decide()中返回DENY值,可以将其应用在Filter链尾,实现如果之前的Filter都没有通过,则该LoggingEvent没有通过,类似或的操作:

1 public class DenyAllFilter extends Filter {
2 public int decide(LoggingEvent event) {
3 return Filter.DENY;
4 }
5 }
StringMatchFilter通过日志消息中的字符串来判断Filter后的状态:

1 public class StringMatchFilter extends Filter {
2 boolean acceptOnMatch = true;
3 String stringToMatch;
4 public int decide(LoggingEvent event) {
5 String msg = event.getRenderedMessage();
6 if (msg == null || stringToMatch == null)
7 return Filter.NEUTRAL;
8 if (msg.indexOf(stringToMatch) == -1) {
9 return Filter.NEUTRAL;
10 } else { // we've got a match
11 if (acceptOnMatch) {
12 return Filter.ACCEPT;
13 } else {
14 return Filter.DENY;
15 }
16 }
17 }
18 }
LevelMatchFilter判断日志级别是否和设置的级别匹配以决定Fi