基于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. 设置myeclipse自动生成的author等注释

    一.window->preference->java->code    styple->code Template 当你选择到这部的时候就会看见右侧有一个框显示出code这个选 ...

  2. ueditor编辑器图片自定义存放目录及路径修改

    百度编辑器ueditor功能强大,很多人士以应用项目开发中,但是里面有一个公众的问题就是上传图片存放目录太深,默认是ueditor/php/upload下,前不久测试后图片存放目录可以改变,但是路径会 ...

  3. PowerDesigner跟表的字段加注释

    选择那个表 右键- >Properties- >Columns- >Customize Columns and Filter(或直接用快捷键Ctrl+U)- >Comment( ...

  4. iOS APNS远程推送(史上最全步骤)

    /*****************************************1************************************************/ waterma ...

  5. 硝烟中的Scrum和XP-我们如何实施Scrum 15)多团队 Part 2/2 16)地理分散 17)检查列表 18)其他

    引入"团队领导"角色 假设有3个团队开发同一个产品 红色的P是PO, 黑色的S是SM, 蓝色是其他团队成员; 如何决定哪些人属于哪个团队? 怎么分配成员? 有人觉得让PO来做人员分 ...

  6. C语言之void类型及void指针 分类: C/C++ 2015-07-13 11:24 8人阅读 评论(0) 收藏

    原文网址:http://www.cnblogs.com/pengyingh/articles/2407267.html 1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在 ...

  7. Android网络:HTTP之利用HttpURLConnection访问网页、获取网络图片实例 (附源码)

    http://blog.csdn.net/yanzi1225627/article/details/22222735 如前文所示的TCP局域网传送东西,除了对传输层的TCP/UDP支持良好外,Andr ...

  8. linux中的网络通信指令 分类: 学习笔记 linux ubuntu 2015-07-06 16:02 134人阅读 评论(0) 收藏

    1.write write命令通信是一对一的通信,即两个人之间的通信,如上图. 效果图 用法:write <用户名> 2.wall wall指令可将信息发送给每位同意接收公众信息的终端机用 ...

  9. Android开发之Activity(活动)

    在安卓中,Activity(活动)就是一个包含应用程序的用户界面的窗口.一个应用程序可以包含一个或多个Activity. 一般一个活动对应一个UI文件,即xml文件.创建活动一般是基础Activity ...

  10. Microsoft Visual Studio Professional 2012 专业版 下载

    记录(以下内容来自网络收集): 下载地址: https://www.microsoft.com/zh-cn/download/details.aspx?id=30682 直接iso连接下载址: htt ...