代码改变世界

log4j源码学习---log打印

2012-08-31 16:47  Polarisary  阅读(492)  评论(1编辑  收藏  举报

接上篇,继续学习log4j源码---log4j打印日志流程

log4j最核心的6个类:
Logger:对日志行为的抽象,封装了不同级别的日志记录接口
Level:对日志级别的抽象
Appender:对日志记录形式的抽象
Layout:对格式的抽象
LoggingEvent:对一次日志记录过程中日志信息的抽象
LoggerRepository:Logger实例的容器

1.首先判断该级别的日志是否可以打印,不能的话直接退出,通过getEffectiveLevel()方法遍历其父Logger直到找到一个有效的Level,并与本日志(logger.info()就是INFO)级别比较小于则调用forcedLog()打印日志

 1 /**
 2 
 3      This is the most generic printing method. It is intended to be
 4      invoked by <b>wrapper</b> classes.
 5 
 6      @param callerFQCN The wrapper class' fully qualified class name.
 7      @param level The level of the logging request.
 8      @param message The message of the logging request.
 9      @param t The throwable of the logging request, may be null.  */
10   public
11   void log(String callerFQCN, Priority level, Object message, Throwable t) {
12     if(repository.isDisabled(level.level)) {
13       return;
14     }
15     if(level.isGreaterOrEqual(this.getEffectiveLevel())) {
16       forcedLog(callerFQCN, level, message, t);
17     }
18   }

2.把日志信息封装成LoggingEvent,并调用callAppenders()委托AppenderAttachableImpl实例遍历所有Appender并调用doAppend()方法,doAppend()会过滤掉一下配置的过滤,再调用append()方法。

 1 /**
 2      Call the appenders in the hierrachy starting at
 3      <code>this</code>.  If no appenders could be found, emit a
 4      warning.
 5 
 6      <p>This method calls all the appenders inherited from the
 7      hierarchy circumventing any evaluation of whether to log or not
 8      to log the particular log request.
 9 
10      @param event the event to log.  */
11   public
12   void callAppenders(LoggingEvent event) {
13     int writes = 0;
14 
15     for(Category c = this; c != null; c=c.parent) {
16       // Protected against simultaneous call to addAppender, removeAppender,...
17       synchronized(c) {
18     if(c.aai != null) {
19       writes += c.aai.appendLoopOnAppenders(event);
20     }
21     if(!c.additive) {
22       break;
23     }
24       }
25     }
26 
27     if(writes == 0) {
28       repository.emitNoAppenderWarning(this);
29     }
30   }

3.以WriterAppender(写入IO流)实例为例,append()方法会先检查是否有Layout,appender是否关闭等,subAppend实现打印。

 1 /**
 2      This method is called by the {@link AppenderSkeleton#doAppend}
 3      method.
 4 
 5      <p>If the output stream exists and is writable then write a log
 6      statement to the output stream. Otherwise, write a single warning
 7      message to <code>System.err</code>.
 8 
 9      <p>The format of the output will depend on this appender's
10      layout.
11 
12   */
13   public
14   void append(LoggingEvent event) {
15 
16     // Reminder: the nesting of calls is:
17     //
18     //    doAppend()
19     //      - check threshold
20     //      - filter
21     //      - append();
22     //        - checkEntryConditions();
23     //        - subAppend();
24 
25     if(!checkEntryConditions()) {
26       return;
27     }
28     subAppend(event);
29    }

4.subAppend()首先格式化打印信息,再判断是否忽略异常信息,如果不忽略,调用getThrowableStrRep()得到对战信息,打印。最后看是否需要立即刷新输出。

其中一些类和方法没有看懂,只能跟下流程   以后继续^_^

                                                                                                                                                                     End……