log4j学习笔记之初始化
最近学了一下log4j,作个标记:
log4j的配置文件有两种格式:xml和properties,分别由类DOMConfigurator和PropertyConfigurator进行处理,在此假设log4j配置文件是xml格式的,看看DOMConfigurator的configure方法
static public void configure(String filename) throws FactoryConfigurationError { new DOMConfigurator().doConfigure(filename,LogManager.getLoggerRepository());}public void doConfigure(final URL url, LoggerRepository repository) { ParseAction action = new ParseAction() { public Document parse(final DocumentBuilder parser) throws SAXException, IOException { URLConnection uConn = url.openConnection(); uConn.setUseCaches(false); InputSource src = new InputSource(uConn.getInputStream()); src.setSystemId(url.toString()); return parser.parse(src); } public String toString() { return "url [" + url.toString() + "]"; } }; doConfigure(action, repository); }private final void doConfigure(final ParseAction action, final LoggerRepository repository) throws FactoryConfigurationError { ... //通过DocumentBuilderFactory取得DocumentBuilder实例docBuilder ... //ParseAction将docBuilder解决成Document Document doc = action.parse(docBuilder); parse(doc.getDocumentElement()); ... }protected void parse(Element element) { //取得根元素,判断合理性 //repository设置一些属性 //获取子元素,做两次遍历,第一次处理categoryFactory和loggerFactory 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);} } } //第二次处理logger和root等 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)) { //处理logger元素 parseCategory(currentElement);} else if (tagName.equals(ROOT_TAG)) { //处理root元素 parseRoot(currentElement);} ...... } }protected void parseCategory (Element loggerElement) { ... String className = subst(loggerElement.getAttribute(CLASS_ATTR)); if(EMPTY_STR.equals(className)) { LogLog.debug("Retreiving an instance of org.apache.log4j.Logger."); //1、如果class没有设置,从repository中获取logger cat = (catFactory == null) ? repository.getLogger(catName) : repository.getLogger(catName, catFactory); } else { LogLog.debug("Desired logger sub-class: ["+className+']'); try { Class clazz = Loader.loadClass(className); Method getInstanceMethod = clazz.getMethod("getLogger", ONE_STRING_PARAM); cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName}); } catch (InvocationTargetException oops) { if (oops.getTargetException() instanceof InterruptedException || oops.getTargetException() instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("Could not retrieve category ["+catName+ "]. Reported error follows.", oops); return; } catch (Exception oops) { LogLog.error("Could not retrieve category ["+catName+ "]. Reported error follows.", oops); return; } } synchronized(cat) { boolean additivity = OptionConverter.toBoolean( subst(loggerElement.getAttribute(ADDITIVITY_ATTR)), true); LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"]."); cat.setAdditivity(additivity); //2、解析子元素 parseChildrenOfLoggerElement(loggerElement, cat, false); } }public Logger getLogger(String name, LoggerFactory factory) {... synchronized(ht) { Object o = ht.get(key); //如果为null,则创建一个logger,并放入hashtable中,更新parent logger if(o == null) {logger = factory.makeNewLoggerInstance(name);logger.setHierarchy(this);ht.put(key, logger);updateParents(logger);return logger; } //如果有,则直接返回 else if(o instanceof Logger) {return (Logger) o; } //有,但是ProvisionNode实例,要同时更新parent logger和children logger else if (o instanceof ProvisionNode) {logger = factory.makeNewLoggerInstance(name);logger.setHierarchy(this);ht.put(key, logger);updateChildren((ProvisionNode) o, logger);updateParents(logger);return logger; } ... } }final private void updateParents(Logger cat) { String name = cat.name; int length = name.length(); boolean parentFound = false; // 尝试取得祖先Logger的实例,可能存在如下情况 //1)、如果父Logger存在,且类型为Logger,则设置为本Logger的父Logger。结束循环。 //2)、如果父Logger存在,且类型为ProvisionNode,则将本Logger添加到ProvisionNode中,然后继续循环。 //3)、如果父Logger不存在,就创建相应的ProvisionNode,则将本Logger添加到ProvisionNode中,然后继续循环。 //2,3中之所以要添加logger到ProvisionNode中,是为了让ProvisionNode中保存所有子Logger的实例,便于后续遍历 for(int i = name.lastIndexOf('.', length-1); i >= 0; i = name.lastIndexOf('.', i-1)) { String substr = name.substring(0, i); //System.out.println("Updating parent : " + substr); CategoryKey key = new CategoryKey(substr); // simple constructor Object o = ht.get(key); // Create a provision node for a future parent. if(o == null) {//System.out.println("No parent "+substr+" found. Creating ProvisionNode.");ProvisionNode pn = new ProvisionNode(cat);ht.put(key, pn); } else if(o instanceof Category) {parentFound = true;cat.parent = (Category) o;//System.out.println("Linking " + cat.name + " -> " + ((Category) o).name);break; // no need to update the ancestors of the closest ancestor } else if(o instanceof ProvisionNode) {((ProvisionNode) o).addElement(cat); } ... }final private void updateChildren(ProvisionNode pn, Logger logger) { final int last = pn.size(); //遍历ProvisionNode中所有的Logger,将不是以logger.name开始的logger设置成其parent logger,在log4j中,x.y是x.y.z的parent logger for(int i = 0; i < last; i++) { Logger l = (Logger) pn.elementAt(i); if(!l.parent.name.startsWith(logger.name)) {logger.parent = l.parent;l.parent = logger; } } }protected void parseChildrenOfLoggerElement(Element catElement, Logger cat, boolean isRoot) { //设置子元素,比如level,additive等 PropertySetter propSetter = new PropertySetter(cat); //清空appenders cat.removeAllAppenders(); NodeList children = catElement.getChildNodes(); final int length = children.getLength(); for (int loop = 0; loop < length; loop++) { Node currentNode = children.item(loop); if (currentNode.getNodeType() == Node.ELEMENT_NODE) {Element currentElement = (Element) currentNode;String tagName = currentElement.getTagName();//如果有设置appender-ref,则为该logger设置此appenderif (tagName.equals(APPENDER_REF_TAG)) { Element appenderRef = (Element) currentNode; Appender appender = findAppenderByReference(appenderRef); String refName = subst(appenderRef.getAttribute(REF_ATTR)); if(appender != null) LogLog.debug("Adding appender named ["+ refName+ "] to category ["+cat.getName()+"]."); else LogLog.debug("Appender named ["+ refName + "] not found."); cat.addAppender(appender); } else if(tagName.equals(LEVEL_TAG)) { parseLevel(currentElement, cat, isRoot);} else if(tagName.equals(PRIORITY_TAG)) { parseLevel(currentElement, cat, isRoot);} else if(tagName.equals(PARAM_TAG)) { setParameter(currentElement, propSetter);} else { quietParseUnrecognizedElement(cat, currentElement, props); } } } propSetter.activate(); } protected Appender findAppenderByReference(Element appenderRef) { String appenderName = subst(appenderRef.getAttribute(REF_ATTR)); Document doc = appenderRef.getOwnerDocument(); return findAppenderByName(doc, appenderName); } protected Appender findAppenderByName(Document doc, String appenderName) { Appender appender = (Appender) appenderBag.get(appenderName); if(appender != null) { return appender; } else { Element element = null; NodeList list = doc.getElementsByTagName("appender"); for (int t=0; t < list.getLength(); t++) {Node node = list.item(t);NamedNodeMap map= node.getAttributes();Node attrNode = map.getNamedItem("name");if (appenderName.equals(attrNode.getNodeValue())) { element = (Element) node; break;} } if(element == null) {LogLog.error("No appender named ["+appenderName+"] could be found."); return null; } else { //调用parseAppender对appender子元素进行解析 appender = parseAppender(element); if (appender != null) { appenderBag.put(appenderName, appender); } return appender; } } } protected Appender parseAppender (Element appenderElement) { ... PropertySetter propSetter = new PropertySetter(appender); ... for (int loop = 0; loop < length; loop++) {if (currentNode.getNodeType() == Node.ELEMENT_NODE) { Element currentElement = (Element)currentNode; // Parse appender parameters if (currentElement.getTagName().equals(PARAM_TAG)) { setParameter(currentElement, propSetter); } // 解析layout else if (currentElement.getTagName().equals(LAYOUT_TAG)) { appender.setLayout(parseLayout(currentElement)); }}... propSetter.activate(); return appender; } ... } protected Layout parseLayout (Element layout_element) { ... //利用反射取得layout的实例,调用了默认构造方法,假设为PatternLayout Object instance = Loader.loadClass(className).newInstance(); Layout layout = (Layout)instance; ...... }public final static String DEFAULT_CONVERSION_PATTERN ="%m%n";private PatternConverter head; public PatternLayout() { this(DEFAULT_CONVERSION_PATTERN); } public PatternLayout(String pattern) { this.pattern = pattern;//将ConversionPattern解析为一个PatternConverter类型的链表//PatternConverter中的next引用下一个ConversionPattern head = createPatternParser((pattern == null) ? DEFAULT_CONVERSION_PATTERN : pattern).parse(); }