基于log4j1.2.17的源代码阅读

org.apache.log4j.xml.DOMConfigurator 类是log4j的xml配置文件初始化类

org.apache.log4j.PropertyConfigurator 类是log4j的properties形式配置文件的初始化类

今天看的是前者

  /**
A static version of {@link #doConfigure(String, LoggerRepository)}. */
static
public
void configure(String filename) throws FactoryConfigurationError {
new DOMConfigurator().doConfigure(filename,
LogManager.getLoggerRepository());
}

一般我们都是讲log4j.xml配置文件放到与src同目录下,方便在class path 的当前路径进行查找(不能放置到src目录里面,不然打包之后也会被打包到类目录下)

 public
void doConfigure(final String filename, LoggerRepository repository) {
ParseAction action = new ParseAction() {
public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
return parser.parse(new File(filename));
}
public String toString() {
return "file [" + filename + "]";
}
};
doConfigure(action, repository);
}

repositroy的作用目前还没有看到

先看下是如何解析xml和初始化相关对象的。

最终会调用DOMConfigurator 类当中的方法

/**
Used internally to configure the log4j framework by parsing a DOM
tree of XML elements based on <a
href="doc-files/log4j.dtd">log4j.dtd</a>. */
protected
void parse(Element element) { String rootElementName = element.getTagName(); if (!rootElementName.equals(CONFIGURATION_TAG)) {
if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
"> element has been deprecated.");
LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
} else {
LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
return;
}
} String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR)); LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
// if the log4j.dtd is not specified in the XML file, then the
// "debug" attribute is returned as the empty string.
if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {
LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
} else {
LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
} //
// reset repository before configuration if reset="true"
// on configuration element.
//
String resetAttrib = subst(element.getAttribute(RESET_ATTR));
LogLog.debug("reset attribute= \"" + resetAttrib +"\".");
if(!("".equals(resetAttrib))) {
if (OptionConverter.toBoolean(resetAttrib, false)) {
repository.resetConfiguration();
}
} String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
if(!confDebug.equals("") && !confDebug.equals("null")) {
LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
} String thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
LogLog.debug("Threshold =\"" + thresholdStr +"\".");
if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
repository.setThreshold(thresholdStr);
} //Hashtable appenderBag = new Hashtable(11); /* Building Appender objects, placing them in a local namespace
for future reference */ // First configure each category factory under the root element.
// Category factories need to be configured before any of
// categories they support.
//
String tagName = null;
Element currentElement = null;
Node currentNode = null;
NodeList children = element.getChildNodes();
final int length = children.getLength(); for (int loop = 0; loop < length; loop++) {
currentNode = children.item(loop);
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
currentElement = (Element) currentNode;
tagName = currentElement.getTagName(); if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
parseCategoryFactory(currentElement);
}
}
} for (int loop = 0; loop < length; loop++) {
currentNode = children.item(loop);
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
currentElement = (Element) currentNode;
tagName = currentElement.getTagName(); if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
parseCategory(currentElement);
} else if (tagName.equals(ROOT_TAG)) {
parseRoot(currentElement);
} else if(tagName.equals(RENDERER_TAG)) {
parseRenderer(currentElement);
} else if(tagName.equals(THROWABLE_RENDERER_TAG)) {
if (repository instanceof ThrowableRendererSupport) {
ThrowableRenderer tr = parseThrowableRenderer(currentElement);
if (tr != null) {
((ThrowableRendererSupport) repository).setThrowableRenderer(tr);
}
}
} else if (!(tagName.equals(APPENDER_TAG)
|| tagName.equals(CATEGORY_FACTORY_TAG)
|| tagName.equals(LOGGER_FACTORY_TAG))) {
quietParseUnrecognizedElement(repository, currentElement, props);
}
}
}
}

通过分析这个方法我们可以看到

1)log4j.xml 中的根tag必须开头是log4j:configuration

如果不是,将会返回错误,并且同时检查是否是老的标签

OLD_CONFIGURATION_TAG ------configuration 如果是的话就打出warn日志,不是打出error日志
2)
在Log4j的源代码当中我们也发现了很多Log日志 ,在Log4j还没有加载完成的时候,利用的是什么打印的呢?
import org.apache.log4j.helpers.LogLog; 利用的就是这个内部帮助类,当我们在log4j.xml的根tag上标注debug=“true”的时候,就会发现这些log日志也打出了,主要是log4j的初始化日志,在quartz当中也可以看到类似的初始化日志

log4j源码阅读的更多相关文章

  1. Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析

    一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...

  2. 搭建 Spring 源码阅读环境

    前言 有一个Spring源码阅读环境是学习Spring的基础.笔者借鉴了网上很多搭建环境的方法,也尝试了很多,接下来总结两种个人认为比较简便实用的方法.读者可根据自己的需要自行选择. 方法一:搭建基础 ...

  3. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  4. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  5. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  6. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  7. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  8. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  9. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

随机推荐

  1. Apache Shiro 集成-Cas

    http://blog.csdn.net/peterwanghao/article/details/8825008 Shiro集成CAS是在1.2版本里新增的功能. Shiro-cas模块将应用作为C ...

  2. js去除空格

    function trim(str){ return str.replace(/(^\s*) | ( \s*$ )/g,"" ); }

  3. js_面向对象编程

    主要内容 值类型与引用类型的特征 深拷贝与浅拷贝 对象的动态特性 构造函数的执行过程 异常处理 dom操作(略) <!DOCTYPE html> <html> <head ...

  4. chrome 插件 vimium 快捷键大全

    DESCRIPTION vimium是一款让你在chrome浏览器能方便地使用键盘操作浏览器的插件.虽然和firefox相比还有些许不足(比如不能按到一些按钮之类的),但是vimium还是做到了能在9 ...

  5. php通过文件头检测文件类型通用类(zip,rar…)(转)

    在做web应用时候,通过web扩展名判断上存文件类型,这个是我们常使用的.有时候我们这样做还不完善.可能有些人上存一些文件,但是他通过修改 扩展名,让在我们的文件类型之内. 单实际访问时候又不能展示( ...

  6. xcode语法高亮插件

    转自http://www.cocoachina.com/bbs/read.php?tid=150107 首先感谢该楼主的亲情贡献@不胜感激! 在Xcode4.6.3中,我使用如下方法放到Plugins ...

  7. PureMVC(JS版)源码解析(九):View类

    在讲解View类之前,我们先回顾一下PureMVC的模块划分:      在PureMVC中M.V.C三部分由三个单例类管理,分别是Model/View/Controller.PureMVC中另外一个 ...

  8. mysql 插入语句

    mysql 插入语句 什么时候用单引号,什么时候不用? 1.先创建一个表 create table user(username varchar(255),age int,marry boolean,b ...

  9. GUI编程笔记(java)01:GUI和CLI

    GUI Graphical User Interface(图形用户接口). 用图形的方式,来显示计算机操作的界面,这样更方便更直观. CLI Command line User Interface ( ...

  10. 30种mysql优化sql语句查询的方法<转>

    转自百度文库 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.   2.应尽量避免在 where 子句中使用!=或<>操作符,否 ...