log4j源码阅读

基于log4j-1.2.15.jar

分析log4j的实现原理

org.apache.log4j.Logger类

package org.apache.log4j;

import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggerRepository;

public class Logger extends Category
{
  private static final String FQCN = Logger.class.getName();

  protected Logger(String name)
  {
    super(name);
  }

  public static Logger getLogger(String name)
  {
    return LogManager.getLogger(name);
  }
  //经常使用的方法
  public static Logger getLogger(Class clazz)
  {
    return LogManager.getLogger(clazz.getName());
  }

  public static Logger getRootLogger()
  {
    return LogManager.getRootLogger();
  }

  public static Logger getLogger(String name, LoggerFactory factory)
  {
    return LogManager.getLogger(name, factory);
  }

  public void trace(Object message)
  {
    if (this.repository.isDisabled(5000)) {
      return;
    }

    if (Level.TRACE.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.TRACE, message, null);
  }

  public void trace(Object message, Throwable t)
  {
    if (this.repository.isDisabled(5000)) {
      return;
    }

    if (Level.TRACE.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.TRACE, message, t);
  }

  public boolean isTraceEnabled()
  {
    if (this.repository.isDisabled(5000)) {
      return false;
    }

    return Level.TRACE.isGreaterOrEqual(getEffectiveLevel());
  }
}

下面是Logger的父类Category类,发现log4j也是大量使用Service Provider机制来完成工具类接口的设计

package org.apache.log4j;

import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Vector;
import org.apache.log4j.helpers.AppenderAttachableImpl;
import org.apache.log4j.helpers.NullEnumeration;
import org.apache.log4j.spi.AppenderAttachable;
import org.apache.log4j.spi.HierarchyEventListener;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggingEvent;

public class Category
  implements AppenderAttachable
{
  protected String name;
  protected volatile Level level;
  protected volatile Category parent;
  private static final String FQCN = Category.class.getName();
  protected ResourceBundle resourceBundle;
  protected LoggerRepository repository;
  AppenderAttachableImpl aai;
  protected boolean additive = true;

  protected Category(String name)
  {
    this.name = name;
  }

  public synchronized void addAppender(Appender newAppender)
  {
    if (this.aai == null) {
      this.aai = new AppenderAttachableImpl();
    }
    this.aai.addAppender(newAppender);
    this.repository.fireAddAppenderEvent(this, newAppender);
  }

  public void assertLog(boolean assertion, String msg)
  {
    if (!assertion)
      error(msg);
  }

  public void callAppenders(LoggingEvent event)
  {
    int writes = 0;

    for (Category c = this; c != null; c = c.parent)
    {
      synchronized (c) {
        if (c.aai != null) {
          writes += c.aai.appendLoopOnAppenders(event);
        }
        if (!c.additive) {
          break;
        }
      }
    }

    if (writes == 0)
      this.repository.emitNoAppenderWarning(this);
  }

  synchronized void closeNestedAppenders()
  {
    Enumeration enumeration = getAllAppenders();
    if (enumeration != null)
      while (enumeration.hasMoreElements()) {
        Appender a = (Appender)enumeration.nextElement();
        if ((a instanceof AppenderAttachable))
          a.close();
      }
  }

  public void debug(Object message)
  {
    if (this.repository.isDisabled(10000))
      return;
    if (Level.DEBUG.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.DEBUG, message, null);
  }

  public void debug(Object message, Throwable t)
  {
    if (this.repository.isDisabled(10000))
      return;
    if (Level.DEBUG.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.DEBUG, message, t);
  }

  public void error(Object message)
  {
    if (this.repository.isDisabled(40000))
      return;
    if (Level.ERROR.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.ERROR, message, null);
  }

  public void error(Object message, Throwable t)
  {
    if (this.repository.isDisabled(40000))
      return;
    if (Level.ERROR.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.ERROR, message, t);
  }

  /** @deprecated */
  public static Logger exists(String name)
  {
    return LogManager.exists(name);
  }

  public void fatal(Object message)
  {
    if (this.repository.isDisabled(50000))
      return;
    if (Level.FATAL.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.FATAL, message, null);
  }

  public void fatal(Object message, Throwable t)
  {
    if (this.repository.isDisabled(50000))
      return;
    if (Level.FATAL.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.FATAL, message, t);
  }

  protected void forcedLog(String fqcn, Priority level, Object message, Throwable t)
  {
    callAppenders(new LoggingEvent(fqcn, this, level, message, t));
  }

  public boolean getAdditivity()
  {
    return this.additive;
  }

  public synchronized Enumeration getAllAppenders()
  {
    if (this.aai == null) {
      return NullEnumeration.getInstance();
    }
    return this.aai.getAllAppenders();
  }

  public synchronized Appender getAppender(String name)
  {
    if ((this.aai == null) || (name == null)) {
      return null;
    }
    return this.aai.getAppender(name);
  }

  public Level getEffectiveLevel()
  {
    for (Category c = this; c != null; c = c.parent) {
      if (c.level != null)
        return c.level;
    }
    return null;
  }

  /** @deprecated */
  public Priority getChainedPriority()
  {
    for (Category c = this; c != null; c = c.parent) {
      if (c.level != null)
        return c.level;
    }
    return null;
  }

  /** @deprecated */
  public static Enumeration getCurrentCategories()
  {
    return LogManager.getCurrentLoggers();
  }

  /** @deprecated */
  public static LoggerRepository getDefaultHierarchy()
  {
    return LogManager.getLoggerRepository();
  }

  /** @deprecated */
  public LoggerRepository getHierarchy()
  {
    return this.repository;
  }

  public LoggerRepository getLoggerRepository()
  {
    return this.repository;
  }

  /** @deprecated */
  public static Category getInstance(String name)
  {
    return LogManager.getLogger(name);
  }

  /** @deprecated */
  public static Category getInstance(Class clazz)
  {
    return LogManager.getLogger(clazz);
  }

  public final String getName()
  {
    return this.name;
  }

  public final Category getParent()
  {
    return this.parent;
  }

  public final Level getLevel()
  {
    return this.level;
  }

  /** @deprecated */
  public final Level getPriority()
  {
    return this.level;
  }

  /** @deprecated */
  public static final Category getRoot()
  {
    return LogManager.getRootLogger();
  }

  public ResourceBundle getResourceBundle()
  {
    for (Category c = this; c != null; c = c.parent) {
      if (c.resourceBundle != null) {
        return c.resourceBundle;
      }
    }
    return null;
  }

  protected String getResourceBundleString(String key)
  {
    ResourceBundle rb = getResourceBundle();

    if (rb == null)
    {
      return null;
    }
    try
    {
      return rb.getString(key);
    }
    catch (MissingResourceException mre) {
      error("No resource is associated with key \"" + key + "\".");
    }return null;
  }

  public void info(Object message)
  {
    if (this.repository.isDisabled(20000))
      return;
    if (Level.INFO.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.INFO, message, null);
  }

  public void info(Object message, Throwable t)
  {
    if (this.repository.isDisabled(20000))
      return;
    if (Level.INFO.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.INFO, message, t);
  }

  public boolean isAttached(Appender appender)
  {
    if ((appender == null) || (this.aai == null)) {
      return false;
    }
    return this.aai.isAttached(appender);
  }

  public boolean isDebugEnabled()
  {
    if (this.repository.isDisabled(10000))
      return false;
    return Level.DEBUG.isGreaterOrEqual(getEffectiveLevel());
  }

  public boolean isEnabledFor(Priority level)
  {
    if (this.repository.isDisabled(level.level))
      return false;
    return level.isGreaterOrEqual(getEffectiveLevel());
  }

  public boolean isInfoEnabled()
  {
    if (this.repository.isDisabled(20000))
      return false;
    return Level.INFO.isGreaterOrEqual(getEffectiveLevel());
  }

  public void l7dlog(Priority priority, String key, Throwable t)
  {
    if (this.repository.isDisabled(priority.level)) {
      return;
    }
    if (priority.isGreaterOrEqual(getEffectiveLevel())) {
      String msg = getResourceBundleString(key);

      if (msg == null) {
        msg = key;
      }
      forcedLog(FQCN, priority, msg, t);
    }
  }

  public void l7dlog(Priority priority, String key, Object[] params, Throwable t)
  {
    if (this.repository.isDisabled(priority.level)) {
      return;
    }
    if (priority.isGreaterOrEqual(getEffectiveLevel())) {
      String pattern = getResourceBundleString(key);
      String msg;
      String msg;
      if (pattern == null)
        msg = key;
      else
        msg = MessageFormat.format(pattern, params);
      forcedLog(FQCN, priority, msg, t);
    }
  }

  public void log(Priority priority, Object message, Throwable t)
  {
    if (this.repository.isDisabled(priority.level)) {
      return;
    }
    if (priority.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, priority, message, t);
  }

  public void log(Priority priority, Object message)
  {
    if (this.repository.isDisabled(priority.level)) {
      return;
    }
    if (priority.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, priority, message, null);
  }

  public void log(String callerFQCN, Priority level, Object message, Throwable t)
  {
    if (this.repository.isDisabled(level.level)) {
      return;
    }
    if (level.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(callerFQCN, level, message, t);
  }

  private void fireRemoveAppenderEvent(Appender appender)
  {
    if (appender != null)
      if ((this.repository instanceof Hierarchy))
        ((Hierarchy)this.repository).fireRemoveAppenderEvent(this, appender);
      else if ((this.repository instanceof HierarchyEventListener))
        ((HierarchyEventListener)this.repository).removeAppenderEvent(this, appender);
  }

  public synchronized void removeAllAppenders()
  {
    if (this.aai != null) {
      Vector appenders = new Vector();
      for (Enumeration iter = this.aai.getAllAppenders(); iter.hasMoreElements(); ) {
        appenders.add(iter.nextElement());
      }
      this.aai.removeAllAppenders();
      for (Enumeration iter = appenders.elements(); iter.hasMoreElements(); ) {
        fireRemoveAppenderEvent((Appender)iter.nextElement());
      }
      this.aai = null;
    }
  }

  public synchronized void removeAppender(Appender appender)
  {
    if ((appender == null) || (this.aai == null))
      return;
    boolean wasAttached = this.aai.isAttached(appender);
    this.aai.removeAppender(appender);
    if (wasAttached)
      fireRemoveAppenderEvent(appender);
  }

  public synchronized void removeAppender(String name)
  {
    if ((name == null) || (this.aai == null)) return;
    Appender appender = this.aai.getAppender(name);
    this.aai.removeAppender(name);
    if (appender != null)
      fireRemoveAppenderEvent(appender);
  }

  public void setAdditivity(boolean additive)
  {
    this.additive = additive;
  }

  final void setHierarchy(LoggerRepository repository)
  {
    this.repository = repository;
  }

  public void setLevel(Level level)
  {
    this.level = level;
  }

  /** @deprecated */
  public void setPriority(Priority priority)
  {
    this.level = ((Level)priority);
  }

  public void setResourceBundle(ResourceBundle bundle)
  {
    this.resourceBundle = bundle;
  }

  /** @deprecated */
  public static void shutdown()
  {
    LogManager.shutdown();
  }

  public void warn(Object message)
  {
    if (this.repository.isDisabled(30000)) {
      return;
    }
    if (Level.WARN.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.WARN, message, null);
  }

  public void warn(Object message, Throwable t)
  {
    if (this.repository.isDisabled(30000))
      return;
    if (Level.WARN.isGreaterOrEqual(getEffectiveLevel()))
      forcedLog(FQCN, Level.WARN, message, t);
  }
}

看一个普通Log4j使用的例子

package com.coderdream.log4j;

import org.apache.log4j.Logger;

public class HelloLog4j {

	private static Logger logger = Logger.getLogger(HelloLog4j.class);

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// System.out.println("This is println message.");

		// 记录debug级别的信息
		logger.debug("This is debug message.");
		// 记录info级别的信息
		logger.info("This is info message.");
		// 记录error级别的信息
		logger.error("This is error message.");
	}
}

配置文件log4j.properties:

#可以设置级别:debug>info>error
#debug:显示debug、info、error
#info:显示info、error
#error:只error
log4j.rootLogger=debug,appender1
#log4j.rootLogger=info,appender1
#log4j.rootLogger=error,appender1  

#输出到控制台
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
#样式为TTCCLayout
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout

结果

[main] DEBUG com.coderdream.log4j.HelloLog4j - This is debug message.
[main] INFO com.coderdream.log4j.HelloLog4j - This is info message.
[main] ERROR com.coderdream.log4j.HelloLog4j - This is error message.

  

  

时间: 2024-10-19 03:18:49

log4j源码阅读的相关文章

log4j源码阅读(一)之Logger

概述 log4j是一款非常方便而且强大的开源日志项目,在经过简单的配置后,可以达到相当不错的效果. 头脑一热决定对log4j的源码进行一定的阅读,其初衷是希望通过源码的阅读,提高写代码的能力. log4j其核心概念可分为: logger 日志接收器,即程序员在自己的代码中使用如logger.error(...)的形式记录日志. append 日志写出器,将logger接收到的日志信息写入到各种设备,如文件,控制台. layout 日志格式化器,将输入的日志先进行格式化,再输出. log4j将日志

Spring源码阅读:Spring JDBC 组件的设计与实现

昨天回忆了我在学习JDBC时自己设计的JDBCTemplate(写在上一篇博客中),在使用Spring过程中,有时会用到Spring给我们提供的JdbcTemplate,这里看看Spring是如何实现这个组件的. 在使用Spring JDBC是你要做的工作很少: 从上面的图上可以看出来,使用Spring JDBC,你只需要做四个工作: 1)定义连接参数:也就是定义url,driver,user,password这个几个参数,一般我们会用一个jdbc.properties文件来配置. 2)指定要执

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划

body, td { font-family: tahoma; font-size: 10pt; } 淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划 SQL编译解析三部曲分为:构建语法树,生成逻辑计划,指定物理执行计划.第一步骤,在我的上一篇博客淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树里做了介绍,这篇博客主要研究第二步,生成逻辑计划. 一. 什么是逻辑计划?我们已经知道,语法树就是一个树状的结构组织,每个节点代表一种类型的语法含义.如

JDK部分源码阅读与理解

本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2016/05/31/JDK部分源码阅读与理解/ 不喜欢重复造轮子,不喜欢贴各种东西.JDK代码什么的,让整篇文章很乱...JDK源码谁都有,没什么好贴的...如果你没看过JDK源码,建议打开Eclipse边看源码边看这篇文章,看过的可以把这篇文章当成是知识点备忘录... JDK容器类中有大量的空指针.数组越界.状态异常等异常处理,这些不是重点,我们关注的应该是它的一些底层的具体实现,这篇

如何阅读Java源码 阅读java的真实体会

刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码很漂亮,但我绝不建议你一开始就读它.我文中会专门谈到这个,暂时不展开. 强烈

Memcache-Java-Client-Release源码阅读(之七)

一.主要内容 本章节的主要内容是介绍Memcache Client的Native,Old_Compat,New_Compat三个Hash算法的应用及实现. 二.准备工作 1.服务器启动192.168.0.106:11211,192.168.0.106:11212两个服务端实例. 2.示例代码: String[] servers = { "192.168.0.106:11211", "192.168.0.106:11212" }; SockIOPool pool =

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder