基于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.