common-logging--源码之SimpleLog
- common-logging源码Log接口
在common-logging的源码中,将log核心类抽象成了一个Log接口。
这里贴出Log接口的源码:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.commons.logging; /**
* A simple logging interface abstracting logging APIs. In order to be
* instantiated successfully by {@link LogFactory}, classes that implement
* this interface must have a constructor that takes a single String
* parameter representing the "name" of this Log.
* <p>
* The six logging levels used by <code>Log</code> are (in order):
* <ol>
* <li>trace (the least serious)</li>
* <li>debug</li>
* <li>info</li>
* <li>warn</li>
* <li>error</li>
* <li>fatal (the most serious)</li>
* </ol>
* The mapping of these log levels to the concepts used by the underlying
* logging system is implementation dependent.
* The implementation should ensure, though, that this ordering behaves
* as expected.
* <p>
* Performance is often a logging concern.
* By examining the appropriate property,
* a component can avoid expensive operations (producing information
* to be logged).
* <p>
* For example,
* <pre>
* if (log.isDebugEnabled()) {
* ... do something expensive ...
* log.debug(theResult);
* }
* </pre>
* <p>
* Configuration of the underlying logging system will generally be done
* external to the Logging APIs, through whatever mechanism is supported by
* that system.
*
* @version $Id: Log.java 1606045 2014-06-27 12:11:56Z tn $
*/
public interface Log { /**
* Logs a message with debug log level.
*
* @param message log this message
*/
void debug(Object message); /**
* Logs an error with debug log level.
*
* @param message log this message
* @param t log this cause
*/
void debug(Object message, Throwable t); /**
* Logs a message with error log level.
*
* @param message log this message
*/
void error(Object message); /**
* Logs an error with error log level.
*
* @param message log this message
* @param t log this cause
*/
void error(Object message, Throwable t); /**
* Logs a message with fatal log level.
*
* @param message log this message
*/
void fatal(Object message); /**
* Logs an error with fatal log level.
*
* @param message log this message
* @param t log this cause
*/
void fatal(Object message, Throwable t); /**
* Logs a message with info log level.
*
* @param message log this message
*/
void info(Object message); /**
* Logs an error with info log level.
*
* @param message log this message
* @param t log this cause
*/
void info(Object message, Throwable t); /**
* Is debug logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than debug.
*
* @return true if debug is enabled in the underlying logger.
*/
boolean isDebugEnabled(); /**
* Is error logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than error.
*
* @return true if error is enabled in the underlying logger.
*/
boolean isErrorEnabled(); /**
* Is fatal logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than fatal.
*
* @return true if fatal is enabled in the underlying logger.
*/
boolean isFatalEnabled(); /**
* Is info logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than info.
*
* @return true if info is enabled in the underlying logger.
*/
boolean isInfoEnabled(); /**
* Is trace logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than trace.
*
* @return true if trace is enabled in the underlying logger.
*/
boolean isTraceEnabled(); /**
* Is warn logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than warn.
*
* @return true if warn is enabled in the underlying logger.
*/
boolean isWarnEnabled(); /**
* Logs a message with trace log level.
*
* @param message log this message
*/
void trace(Object message); /**
* Logs an error with trace log level.
*
* @param message log this message
* @param t log this cause
*/
void trace(Object message, Throwable t); /**
* Logs a message with warn log level.
*
* @param message log this message
*/
void warn(Object message); /**
* Logs an error with warn log level.
*
* @param message log this message
* @param t log this cause
*/
void warn(Object message, Throwable t);
}
- common-logging源码simpleLog类
前面的博客中,我自己模拟写了一套log4j,这里贴出common-logging中的一个简单例子源码,大致的代码比我前面写的有点差不多,只不过几个值得性能上注意的点还是值得学习的。
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.commons.logging.impl; import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogConfigurationException; /**
* Simple implementation of Log that sends all enabled log messages,
* for all defined loggers, to System.err. The following system properties
* are supported to configure the behavior of this logger:
* <ul>
* <li><code>org.apache.commons.logging.simplelog.defaultlog</code> -
* Default logging detail level for all instances of SimpleLog.
* Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
* If not specified, defaults to "info". </li>
* <li><code>org.apache.commons.logging.simplelog.log.xxxxx</code> -
* Logging detail level for a SimpleLog instance named "xxxxx".
* Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
* If not specified, the default logging detail level is used.</li>
* <li><code>org.apache.commons.logging.simplelog.showlogname</code> -
* Set to <code>true</code> if you want the Log instance name to be
* included in output messages. Defaults to <code>false</code>.</li>
* <li><code>org.apache.commons.logging.simplelog.showShortLogname</code> -
* Set to <code>true</code> if you want the last component of the name to be
* included in output messages. Defaults to <code>true</code>.</li>
* <li><code>org.apache.commons.logging.simplelog.showdatetime</code> -
* Set to <code>true</code> if you want the current date and time
* to be included in output messages. Default is <code>false</code>.</li>
* <li><code>org.apache.commons.logging.simplelog.dateTimeFormat</code> -
* The date and time format to be used in the output messages.
* The pattern describing the date and time format is the same that is
* used in <code>java.text.SimpleDateFormat</code>. If the format is not
* specified or is invalid, the default format is used.
* The default format is <code>yyyy/MM/dd HH:mm:ss:SSS zzz</code>.</li>
* </ul>
* <p>
* In addition to looking for system properties with the names specified
* above, this implementation also checks for a class loader resource named
* <code>"simplelog.properties"</code>, and includes any matching definitions
* from this resource (if it exists).
*
* @version $Id: SimpleLog.java 1435115 2013-01-18 12:40:19Z tn $
*/
public class SimpleLog implements Log, Serializable { /** Serializable version identifier. */
private static final long serialVersionUID = 136942970684951178L; // ------------------------------------------------------- Class Attributes /** All system properties used by <code>SimpleLog</code> start with this */
static protected final String systemPrefix = "org.apache.commons.logging.simplelog."; /** Properties loaded from simplelog.properties */
static protected final Properties simpleLogProps = new Properties(); /** The default format to use when formating dates */
static protected final String DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss:SSS zzz"; /** Include the instance name in the log message? */
static volatile protected boolean showLogName = false; /** Include the short name ( last component ) of the logger in the log
* message. Defaults to true - otherwise we'll be lost in a flood of
* messages without knowing who sends them.
*/
static volatile protected boolean showShortName = true; /** Include the current time in the log message */
static volatile protected boolean showDateTime = false; /** The date and time format to use in the log message */
static volatile protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; /**
* Used to format times.
* <p>
* Any code that accesses this object should first obtain a lock on it,
* ie use synchronized(dateFormatter); this requirement was introduced
* in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format
* is not thread-safe).
*/
static protected DateFormat dateFormatter = null; // ---------------------------------------------------- Log Level Constants /** "Trace" level logging. */
public static final int LOG_LEVEL_TRACE = 1;
/** "Debug" level logging. */
public static final int LOG_LEVEL_DEBUG = 2;
/** "Info" level logging. */
public static final int LOG_LEVEL_INFO = 3;
/** "Warn" level logging. */
public static final int LOG_LEVEL_WARN = 4;
/** "Error" level logging. */
public static final int LOG_LEVEL_ERROR = 5;
/** "Fatal" level logging. */
public static final int LOG_LEVEL_FATAL = 6; /** Enable all logging levels */
public static final int LOG_LEVEL_ALL = LOG_LEVEL_TRACE - 1; /** Enable no logging levels */
public static final int LOG_LEVEL_OFF = LOG_LEVEL_FATAL + 1; // ------------------------------------------------------------ Initializer private static String getStringProperty(String name) {
String prop = null;
try {
prop = System.getProperty(name);
} catch (SecurityException e) {
// Ignore
}
return prop == null ? simpleLogProps.getProperty(name) : prop;
} private static String getStringProperty(String name, String dephault) {
String prop = getStringProperty(name);
return prop == null ? dephault : prop;
} private static boolean getBooleanProperty(String name, boolean dephault) {
String prop = getStringProperty(name);
return prop == null ? dephault : "true".equalsIgnoreCase(prop);
} // Initialize class attributes.
// Load properties file, if found.
// Override with system properties.
static {
// Add props from the resource simplelog.properties
InputStream in = getResourceAsStream("simplelog.properties");
if(null != in) {
try {
simpleLogProps.load(in);
in.close();
} catch(java.io.IOException e) {
// ignored
}
} showLogName = getBooleanProperty(systemPrefix + "showlogname", showLogName);
showShortName = getBooleanProperty(systemPrefix + "showShortLogname", showShortName);
showDateTime = getBooleanProperty(systemPrefix + "showdatetime", showDateTime); if(showDateTime) {
dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat",
dateTimeFormat);
try {
dateFormatter = new SimpleDateFormat(dateTimeFormat);
} catch(IllegalArgumentException e) {
// If the format pattern is invalid - use the default format
dateTimeFormat = DEFAULT_DATE_TIME_FORMAT;
dateFormatter = new SimpleDateFormat(dateTimeFormat);
}
}
} // ------------------------------------------------------------- Attributes /** The name of this simple log instance */
protected volatile String logName = null;
/** The current log level */
protected volatile int currentLogLevel;
/** The short name of this simple log instance */
private volatile String shortLogName = null; // ------------------------------------------------------------ Constructor /**
* Construct a simple log with given name.
*
* @param name log name
*/
public SimpleLog(String name) {
logName = name; // Set initial log level
// Used to be: set default log level to ERROR
// IMHO it should be lower, but at least info ( costin ).
setLevel(SimpleLog.LOG_LEVEL_INFO); // Set log level from properties
String lvl = getStringProperty(systemPrefix + "log." + logName);
int i = String.valueOf(name).lastIndexOf(".");
while(null == lvl && i > -1) {
name = name.substring(0,i);
lvl = getStringProperty(systemPrefix + "log." + name);
i = String.valueOf(name).lastIndexOf(".");
} if(null == lvl) {
lvl = getStringProperty(systemPrefix + "defaultlog");
} if("all".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_ALL);
} else if("trace".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_TRACE);
} else if("debug".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_DEBUG);
} else if("info".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_INFO);
} else if("warn".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_WARN);
} else if("error".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_ERROR);
} else if("fatal".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_FATAL);
} else if("off".equalsIgnoreCase(lvl)) {
setLevel(SimpleLog.LOG_LEVEL_OFF);
}
} // -------------------------------------------------------- Properties /**
* Set logging level.
*
* @param currentLogLevel new logging level
*/
public void setLevel(int currentLogLevel) {
this.currentLogLevel = currentLogLevel;
} /**
* Get logging level.
*/
public int getLevel() {
return currentLogLevel;
} // -------------------------------------------------------- Logging Methods /**
* Do the actual logging.
* <p>
* This method assembles the message and then calls <code>write()</code>
* to cause it to be written.
*
* @param type One of the LOG_LEVEL_XXX constants defining the log level
* @param message The message itself (typically a String)
* @param t The exception whose stack trace should be logged
*/
protected void log(int type, Object message, Throwable t) {
// Use a string buffer for better performance
final StringBuffer buf = new StringBuffer(); // Append date-time if so configured
if(showDateTime) {
final Date now = new Date();
String dateText;
synchronized(dateFormatter) {
dateText = dateFormatter.format(now);
}
buf.append(dateText);
buf.append(" ");
} // Append a readable representation of the log level
switch(type) {
case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break;
case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break;
case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO] "); break;
case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN] "); break;
case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break;
case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break;
} // Append the name of the log instance if so configured
if(showShortName) {
if(shortLogName == null) {
// Cut all but the last component of the name for both styles
final String slName = logName.substring(logName.lastIndexOf(".") + 1);
shortLogName = slName.substring(slName.lastIndexOf("/") + 1);
}
buf.append(String.valueOf(shortLogName)).append(" - ");
} else if(showLogName) {
buf.append(String.valueOf(logName)).append(" - ");
} // Append the message
buf.append(String.valueOf(message)); // Append stack trace if not null
if(t != null) {
buf.append(" <");
buf.append(t.toString());
buf.append(">"); final java.io.StringWriter sw = new java.io.StringWriter(1024);
final java.io.PrintWriter pw = new java.io.PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
buf.append(sw.toString());
} // Print to the appropriate destination
write(buf);
} /**
* Write the content of the message accumulated in the specified
* <code>StringBuffer</code> to the appropriate output destination. The
* default implementation writes to <code>System.err</code>.
*
* @param buffer A <code>StringBuffer</code> containing the accumulated
* text to be logged
*/
protected void write(StringBuffer buffer) {
System.err.println(buffer.toString());
} /**
* Is the given log level currently enabled?
*
* @param logLevel is this level enabled?
*/
protected boolean isLevelEnabled(int logLevel) {
// log level are numerically ordered so can use simple numeric
// comparison
return logLevel >= currentLogLevel;
} // -------------------------------------------------------- Log Implementation /**
* Logs a message with
* <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#debug(Object)
*/
public final void debug(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
log(SimpleLog.LOG_LEVEL_DEBUG, message, null);
}
} /**
* Logs a message with
* <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#debug(Object, Throwable)
*/
public final void debug(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
log(SimpleLog.LOG_LEVEL_DEBUG, message, t);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#trace(Object)
*/
public final void trace(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
log(SimpleLog.LOG_LEVEL_TRACE, message, null);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#trace(Object, Throwable)
*/
public final void trace(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
log(SimpleLog.LOG_LEVEL_TRACE, message, t);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#info(Object)
*/
public final void info(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
log(SimpleLog.LOG_LEVEL_INFO,message,null);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#info(Object, Throwable)
*/
public final void info(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
log(SimpleLog.LOG_LEVEL_INFO, message, t);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#warn(Object)
*/
public final void warn(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
log(SimpleLog.LOG_LEVEL_WARN, message, null);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#warn(Object, Throwable)
*/
public final void warn(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
log(SimpleLog.LOG_LEVEL_WARN, message, t);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#error(Object)
*/
public final void error(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
log(SimpleLog.LOG_LEVEL_ERROR, message, null);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#error(Object, Throwable)
*/
public final void error(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
log(SimpleLog.LOG_LEVEL_ERROR, message, t);
}
} /**
* Log a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>.
*
* @param message to log
* @see org.apache.commons.logging.Log#fatal(Object)
*/
public final void fatal(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
log(SimpleLog.LOG_LEVEL_FATAL, message, null);
}
} /**
* Logs a message with <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>.
*
* @param message to log
* @param t log this cause
* @see org.apache.commons.logging.Log#fatal(Object, Throwable)
*/
public final void fatal(Object message, Throwable t) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
log(SimpleLog.LOG_LEVEL_FATAL, message, t);
}
} /**
* Are debug messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isDebugEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG);
} /**
* Are error messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isErrorEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR);
} /**
* Are fatal messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isFatalEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL);
} /**
* Are info messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isInfoEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO);
} /**
* Are trace messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isTraceEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE);
} /**
* Are warn messages currently enabled?
* <p>
* This allows expensive operations such as <code>String</code>
* concatenation to be avoided when the message will be ignored by the
* logger.
*/
public final boolean isWarnEnabled() {
return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN);
} /**
* Return the thread context class loader if available.
* Otherwise return null.
*
* The thread context class loader is available for JDK 1.2
* or later, if certain security conditions are met.
*
* @exception LogConfigurationException if a suitable class loader
* cannot be identified.
*/
private static ClassLoader getContextClassLoader() {
ClassLoader classLoader = null; try {
// Are we running on a JDK 1.2 or later system?
final Method method = Thread.class.getMethod("getContextClassLoader", (Class[]) null); // Get the thread context class loader (if there is one)
try {
classLoader = (ClassLoader)method.invoke(Thread.currentThread(), (Class[]) null);
} catch (IllegalAccessException e) {
// ignore
} catch (InvocationTargetException e) {
/**
* InvocationTargetException is thrown by 'invoke' when
* the method being invoked (getContextClassLoader) throws
* an exception.
*
* getContextClassLoader() throws SecurityException when
* the context class loader isn't an ancestor of the
* calling class's class loader, or if security
* permissions are restricted.
*
* In the first case (not related), we want to ignore and
* keep going. We cannot help but also ignore the second
* with the logic below, but other calls elsewhere (to
* obtain a class loader) will trigger this exception where
* we can make a distinction.
*/
if (e.getTargetException() instanceof SecurityException) {
// ignore
} else {
// Capture 'e.getTargetException()' exception for details
// alternate: log 'e.getTargetException()', and pass back 'e'.
throw new LogConfigurationException
("Unexpected InvocationTargetException", e.getTargetException());
}
}
} catch (NoSuchMethodException e) {
// Assume we are running on JDK 1.1
// ignore
} if (classLoader == null) {
classLoader = SimpleLog.class.getClassLoader();
} // Return the selected class loader
return classLoader;
} private static InputStream getResourceAsStream(final String name) {
return (InputStream)AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
ClassLoader threadCL = getContextClassLoader(); if (threadCL != null) {
return threadCL.getResourceAsStream(name);
} else {
return ClassLoader.getSystemResourceAsStream(name);
}
}
});
}
}
- simpleLog类值得借鉴的地方
1,simpleLog也同样定义了几个静态常量用来保存从配置文件中读取出来的日志输出控制字段,在这里用了volatile关键字修饰,避免了线程问题。关于volatile关键字我前面的博客里面有,在写完自己的一套web框架后,我会认真的整理下并发编程,关于这块短板以后会补充起来。
2,simpleLog类中几个输出日志的方法,比如debug(),info()等在调用核心log()方法之前都先加一个逻辑控制。
public final void debug(Object message) {
if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
log(SimpleLog.LOG_LEVEL_DEBUG, message, null);
}
}
代码相对比较严谨,而且这里加一个开关也控制了不必要的性能消耗,当然这个开关也直接拎出来了,我们在实际的业务代码中写日志输出的时候也可以调用来加上控制,提高性能,比如减少一些输出日志的字符串连接等等。
protected boolean isLevelEnabled(int logLevel) {
// log level are numerically ordered so can use simple numeric
// comparison
return logLevel >= currentLogLevel;
}
3,从properties文件中读取配置的几个方法,特别是读取Boolean类型属性的方法,以后我们就不要老土的用Boolean.booleanValue()了,用一个字符串.equals()就OK。
private static boolean getBooleanProperty(String name, boolean dephault) {
String prop = getStringProperty(name);
return prop == null ? dephault : "true".equalsIgnoreCase(prop);
}
4,加载配置文件获得一个输入流的方法,使用了JDK的几个安全类,这里贴出源码,以后也可以直接拿来使用。
private static ClassLoader getContextClassLoader() {
ClassLoader classLoader = null; try {
// Are we running on a JDK 1.2 or later system?
final Method method = Thread.class.getMethod("getContextClassLoader", (Class[]) null); // Get the thread context class loader (if there is one)
try {
classLoader = (ClassLoader)method.invoke(Thread.currentThread(), (Class[]) null);
} catch (IllegalAccessException e) {
// ignore
} catch (InvocationTargetException e) {
/**
* InvocationTargetException is thrown by 'invoke' when
* the method being invoked (getContextClassLoader) throws
* an exception.
*
* getContextClassLoader() throws SecurityException when
* the context class loader isn't an ancestor of the
* calling class's class loader, or if security
* permissions are restricted.
*
* In the first case (not related), we want to ignore and
* keep going. We cannot help but also ignore the second
* with the logic below, but other calls elsewhere (to
* obtain a class loader) will trigger this exception where
* we can make a distinction.
*/
if (e.getTargetException() instanceof SecurityException) {
// ignore
} else {
// Capture 'e.getTargetException()' exception for details
// alternate: log 'e.getTargetException()', and pass back 'e'.
throw new LogConfigurationException
("Unexpected InvocationTargetException", e.getTargetException());
}
}
} catch (NoSuchMethodException e) {
// Assume we are running on JDK 1.1
// ignore
} if (classLoader == null) {
classLoader = SimpleLog.class.getClassLoader();
} // Return the selected class loader
return classLoader;
} private static InputStream getResourceAsStream(final String name) {
return (InputStream)AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
ClassLoader threadCL = getContextClassLoader(); if (threadCL != null) {
return threadCL.getResourceAsStream(name);
} else {
return ClassLoader.getSystemResourceAsStream(name);
}
}
});
}
- 总结
Commons Logging的设计比较简单,它定义了一个Log接口,所有它支持的日志系统都有相应的Log实现类,如Log4JLogger、Jdk14Logger、Jdk13LumberjackLogger、SimpleLog、NoOpLog、AvalonLogger、LogKitLogger等类,在
LogFactory中定义了一定的规则,从而根据当前的环境和配置取得特定的Log子类实例。关于它是如何去获取特定Log实现的,我下一篇博客会整理到。
common-logging--源码之SimpleLog的更多相关文章
- Common.Logging源码解析二
Common.Logging源码解析一分析了LogManager主入口的整个逻辑,其中第二步生成日志实例工厂类接口分析的很模糊,本随笔将会详细讲解整个日志实例工厂类接口的生成过程! (1).关于如何生 ...
- Common.Logging源码解析一
Common.Logging是Apache下的一个开源日志接口组件,主要用于切换不同的日志库,因为当前流行的日志库有很多向log4j.log4net(log4j的.net版本)等等,所以为了能灵活的切 ...
- 基于Common.Logging + Log4Net实现的日志管理
前言 Common.Logging 是Commons-Logging(apache最早提供的日志门面接口,提供了简单的日志实现以及日志解耦功能) 项目的.net版本.其目的是为 "所有的.n ...
- Spring源码解析-AOP简单分析
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等,不需要去修改业务相关的代码. 对于这部分内容,同样采用一个简单的例子和源码来说明. 接口 public ...
- Vue 源码解读(1)—— 前言
当学习成为了习惯,知识也就变成了常识. 感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/blog ...
- Caffe源码中common文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中的一些重要头文件如caffe.hpp.blob.hpp等或者外部调用Caffe库使用时,一般都会in ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- ASP.NET Core 源码学习之 Logging[1]:Introduction
在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了.而在 ASP.Net Core 中内置了日志系统, ...
- ASP.NET Core 源码学习之 Logging[2]:Configure
在上一章中,我们对 ASP.NET Logging 系统做了一个整体的介绍,而在本章中则开始从最基本的配置开始,逐步深入到源码当中去. 默认配置 在 ASP.NET Core 2.0 中,对默认配置做 ...
- ASP.NET Core 源码学习之 Logging[3]:Logger
上一章,我们介绍了日志的配置,在熟悉了配置之后,自然是要了解一下在应用程序中如何使用,而本章则从最基本的使用开始,逐步去了解去源码. LoggerFactory 我们可以在构造函数中注入 ILogge ...
随机推荐
- Mysql:执行source sql脚本时,出现:error 2
Centos下部署mysql: 1.yum -y install mysql*; 2.service mysqld start; 3.chkconfig mysqld on; 4.设置用户名和密码:m ...
- docker:(5)利用docker -v 和 Publish over SSH插件实现war包自动部署到docker
在 docker:(3)docker容器挂载宿主主机目录 中介绍了运行docker时的一个重要命令 -v sudo docker run -p : --name tomcat_xiao_volume ...
- MFC中属性表单和向导对话框的使用
每次在使用MFC创建一个框架时,需要一步步选择自己的程序的外观,基本功能等选项,最后MFC会生成一个基本的程序框架,这个就是向导对话框:而属性表单则是另外一种对话框,表单上有多个属性页,每点击某一页, ...
- 使用CJSON库实现XML与JSON格式的相互转化
之前完成了一个两个平台对接的项目.由于这两个平台一个是使用json格式的数据,一个是使用xml格式的数据,要实现它们二者的对接就涉及到这两个数据格式的转化,在查阅相关资料的时候发现了这个CJSON库, ...
- vim 简单笔记
vim编辑器Linux系统常用的一种编辑器 有三种模式 命令模式:插入模式:编辑模式 1 插入模式的基本操作: 从命令模式切入到插入模式只需要注意有三个字母aio就可以了 a是在当前光标后插入 ...
- iOS QQ分享图片无反应问题
受iOS 9 上 http 限制 需要在info.plist文件添加必要string <key>LSApplicationQueriesSchemes</key> <ar ...
- [转]python变量作用域的有趣差别
func()里 可以访问全局变量i,但不能给i重新赋值. i = 1 def func(): print( i + 1) func() # 2 用global声明后,可以给i重新赋值. i = 1 d ...
- RHM-M10汽车吊力矩限制器/载荷指示器
一 产品特点 1. 采用7.0寸工业65K色TFT LCD真彩屏,亮度250nit,分辨率800×480: 2. 传感器采用进口机芯,过载能力强: 3. 采用油压取力和大臂弯曲 ...
- python实现求最长子串长度
给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最长回文子串是'3553',所以返回4. 最容易想到的办法是枚举出所有的子串,然后一一判断是否为回文串,返回最长的回文子 ...
- UVA 11039-Building designing【贪心+绝对值排序】
UVA11039-Building designing Time limit: 3.000 seconds An architect wants to design a very high build ...