2021SC@SDUSC
目录
Log包
SLF4JLoggerFactory.java
源码展示
代码分析
关于slf4j
Logger.java
源码展示
源码分析
Log包
本篇主要来分析LoggerFactory的余下代码和Logger代码
SLF4JLoggerFactory.java
源码展示
package freemarker.log;
import org.slf4j.spi.LocationAwareLogger;
// 2.4: Remove
@Deprecated
public class SLF4JLoggerFactory implements LoggerFactory {
@Override
public Logger getLogger(String category) {
org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger(category);
if (slf4jLogger instanceof LocationAwareLogger) {
return new LocationAwareSLF4JLogger((LocationAwareLogger) slf4jLogger);
} else {
return new LocationUnawareSLF4JLogger(slf4jLogger);
}
}
private static final class LocationAwareSLF4JLogger extends Logger {
private static final String ADAPTER_FQCN
= LocationAwareSLF4JLogger.class.getName();
private final LocationAwareLogger logger;
LocationAwareSLF4JLogger(LocationAwareLogger logger) {
this.logger = logger;
}
@Override
public void debug(String message) {
debug(message, null);
}
@Override
public void debug(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.DEBUG_INT, message, null, t);
}
@Override
public void info(String message) {
info(message, null);
}
@Override
public void info(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.INFO_INT, message, null, t);
}
@Override
public void warn(String message) {
warn(message, null);
}
@Override
public void warn(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.WARN_INT, message, null, t);
}
@Override
public void error(String message) {
error(message, null);
}
@Override
public void error(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.ERROR_INT, message, null, t);
}
@Override
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
@Override
public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}
@Override
public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}
@Override
public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}
@Override
public boolean isFatalEnabled() {
return logger.isErrorEnabled();
}
}
private static class LocationUnawareSLF4JLogger extends Logger {
private final org.slf4j.Logger logger;
LocationUnawareSLF4JLogger(org.slf4j.Logger logger) {
this.logger = logger;
}
@Override
public void debug(String message) {
logger.debug(message);
}
@Override
public void debug(String message, Throwable t) {
logger.debug(message, t);
}
@Override
public void info(String message) {
logger.info(message);
}
@Override
public void info(String message, Throwable t) {
logger.info(message, t);
}
@Override
public void warn(String message) {
logger.warn(message);
}
@Override
public void warn(String message, Throwable t) {
logger.warn(message, t);
}
@Override
public void error(String message) {
logger.error(message);
}
@Override
public void error(String message, Throwable t) {
logger.error(message, t);
}
@Override
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
@Override
public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}
@Override
public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}
@Override
public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}
@Override
public boolean isFatalEnabled() {
return logger.isErrorEnabled();
}
}
}
代码分析
package freemarker.log;
import org.slf4j.spi.LocationAwareLogger;
// 2.4: Remove
@Deprecated
public class SLF4JLoggerFactory implements LoggerFactory {
@Override
public Logger getLogger(String category) {
org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger(category);
if (slf4jLogger instanceof LocationAwareLogger) {
return new LocationAwareSLF4JLogger((LocationAwareLogger) slf4jLogger);
} else {
return new LocationUnawareSLF4JLogger(slf4jLogger);
}
}
private static final class LocationAwareSLF4JLogger extends Logger {
private static final String ADAPTER_FQCN
= LocationAwareSLF4JLogger.class.getName();
private final LocationAwareLogger logger;
LocationAwareSLF4JLogger(LocationAwareLogger logger) {
this.logger = logger;
}
@Override
public void debug(String message) {
debug(message, null);
}
@Override
public void debug(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.DEBUG_INT, message, null, t);
}
@Override
public void info(String message) {
info(message, null);
}
@Override
public void info(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.INFO_INT, message, null, t);
}
@Override
public void warn(String message) {
warn(message, null);
}
@Override
public void warn(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.WARN_INT, message, null, t);
}
@Override
public void error(String message) {
error(message, null);
}
@Override
public void error(String message, Throwable t) {
logger.log(null, ADAPTER_FQCN,
LocationAwareLogger.ERROR_INT, message, null, t);
}
@Override
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
@Override
public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}
@Override
public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}
@Override
public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}
@Override
public boolean isFatalEnabled() {
return logger.isErrorEnabled();
}
}
private static class LocationUnawareSLF4JLogger extends Logger {
private final org.slf4j.Logger logger;
LocationUnawareSLF4JLogger(org.slf4j.Logger logger) {
this.logger = logger;
}
@Override
public void debug(String message) {
logger.debug(message);
}
@Override
public void debug(String message, Throwable t) {
logger.debug(message, t);
}
@Override
public void info(String message) {
logger.info(message);
}
@Override
public void info(String message, Throwable t) {
logger.info(message, t);
}
@Override
public void warn(String message) {
logger.warn(message);
}
@Override
public void warn(String message, Throwable t) {
logger.warn(message, t);
}
@Override
public void error(String message) {
logger.error(message);
}
@Override
public void error(String message, Throwable t) {
logger.error(message, t);
}
@Override
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
@Override
public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}
@Override
public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}
@Override
public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}
@Override
public boolean isFatalEnabled() {
return logger.isErrorEnabled();
}
}
}
代码分析
获取Logger的一个对象,重新定义父类的方法,申明 logger 变量
public Logger getLogger(String category) {
org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger(category);
if (slf4jLogger instanceof LocationAwareLogger) {
return new LocationAwareSLF4JLogger((LocationAwareLogger) slf4jLogger);
} else {
return new LocationUnawareSLF4JLogger(slf4jLogger);
}
}
关于slf4j
经过查阅资料分析后得知:
SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志类库。
SLF4J使你的代码独立于任意一个特定的日志API,编写供内外部都可以使用的API或者通用类库,那么你真不会希望使用你类库的客户端必须使用你选择的日志类库
SLF4J的占位符就比这个好用得多。所以, 一般应用使用日志框架都是基于slf4j的;
- 创建Logger对象: slf4j.Logger LOG= slf4j.LoggerFactory.getLogger(className);
- 一般使用接口: LOG.info(msg), LOG.debug(msg), LOG.warn(msg)...
- 有异常追踪的: LOG.info(msg,ex), LOG.debug(msg,ex), LOG.warn(msg,ex)...
Logger.java
源码展示
package freemarker.log;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
public abstract class Logger {
public static final String SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY = "org.freemarker.loggerLibrary";
public static final int LIBRARY_AUTO = -1;
private static final int MIN_LIBRARY_ENUM = LIBRARY_AUTO;
public static final String LIBRARY_NAME_AUTO = "auto";
public static final int LIBRARY_NONE = 0;
public static final String LIBRARY_NAME_NONE = "none";
public static final int LIBRARY_JAVA = 1;
public static final String LIBRARY_NAME_JUL = "JUL";
@Deprecated
public static final int LIBRARY_AVALON = 2;
// This value is also used as part of the factory class name.
@Deprecated
public static final String LIBRARY_NAME_AVALON = "Avalon";
public static final int LIBRARY_LOG4J = 3;
// This value is also used as part of the factory class name.
public static final String LIBRARY_NAME_LOG4J = "Log4j";
public static final int LIBRARY_COMMONS = 4;
// This value is also used as part of the factory class name.
public static final String LIBRARY_NAME_COMMONS_LOGGING = "CommonsLogging";
public static final int LIBRARY_SLF4J = 5;
// This value is also used as part of the factory class name.
public static final String LIBRARY_NAME_SLF4J = "SLF4J";
private static final int MAX_LIBRARY_ENUM = LIBRARY_SLF4J;
private static final String REAL_LOG4J_PRESENCE_CLASS = "org.apache.log4j.FileAppender";
private static final String LOG4J_OVER_SLF4J_TESTER_CLASS = "freemarker.log._Log4jOverSLF4JTester";
private static final String[] LIBRARIES_BY_PRIORITY = {
null, LIBRARY_NAME_JUL,
"org.apache.log.Logger", LIBRARY_NAME_AVALON,
"org.apache.log4j.Logger", LIBRARY_NAME_LOG4J,
"org.apache.commons.logging.Log", LIBRARY_NAME_COMMONS_LOGGING,
"org.slf4j.Logger", LIBRARY_NAME_SLF4J,
};
private static String getAvailabilityCheckClassName(int libraryEnum) {
if (libraryEnum == LIBRARY_AUTO || libraryEnum == LIBRARY_NONE) {
// Statically linked
return null;
}
return LIBRARIES_BY_PRIORITY[(libraryEnum - 1) * 2];
}
static {
if (LIBRARIES_BY_PRIORITY.length / 2 != MAX_LIBRARY_ENUM) {
throw new AssertionError();
}
}
private static String getLibraryName(int libraryEnum) {
if (libraryEnum == LIBRARY_AUTO) {
return LIBRARY_NAME_AUTO;
}
if (libraryEnum == LIBRARY_NONE) {
return LIBRARY_NAME_NONE;
}
return LIBRARIES_BY_PRIORITY[(libraryEnum - 1) * 2 + 1];
}
private static boolean isAutoDetected(int libraryEnum) {
// 2.4: Remove libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS
return !(libraryEnum == LIBRARY_AUTO || libraryEnum == LIBRARY_NONE
|| libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS);
}
private static int libraryEnum;
private static LoggerFactory loggerFactory;
private static boolean initializedFromSystemProperty;
private static String categoryPrefix = "";
private static final Map loggersByCategory = new HashMap();
@Deprecated
public static void selectLoggerLibrary(int libraryEnum) throws ClassNotFoundException {
if (libraryEnum < MIN_LIBRARY_ENUM || libraryEnum > MAX_LIBRARY_ENUM) {
throw new IllegalArgumentException("Library enum value out of range");
}
synchronized (Logger.class) {
final boolean loggerFactoryWasAlreadySet = loggerFactory != null;
if (!loggerFactoryWasAlreadySet || libraryEnum != Logger.libraryEnum) {
// Creates the factory only if it can be done based on system property:
ensureLoggerFactorySet(true);
// The system property has precedence because this method was deprecated by it:
if (!initializedFromSystemProperty || loggerFactory == null) {
int replacedLibraryEnum = Logger.libraryEnum;
setLibrary(libraryEnum);
loggersByCategory.clear();
if (loggerFactoryWasAlreadySet) {
logWarnInLogger("Logger library was already set earlier to ""
+ getLibraryName(replacedLibraryEnum) + ""; "
+ "change to "" + getLibraryName(libraryEnum) + "" won't effect loggers created "
+ "earlier.");
}
} else if (libraryEnum != Logger.libraryEnum) {
logWarnInLogger("Ignored " + Logger.class.getName() + ".selectLoggerLibrary(""
+ getLibraryName(libraryEnum)
+ "") call, because the "" + SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY
+ "" system property is set to "" + getLibraryName(Logger.libraryEnum) + "".");
}
}
}
}
@Deprecated
public static void setCategoryPrefix(String prefix) {
synchronized (Logger.class) {
if (prefix == null) {
throw new IllegalArgumentException();
}
categoryPrefix = prefix;
}
}
public abstract void debug(String message);
public abstract void debug(String message, Throwable t);
public abstract void info(String message);
public abstract void info(String message, Throwable t);
public abstract void warn(String message);
public abstract void warn(String message, Throwable t);
public abstract void error(String message);
public abstract void error(String message, Throwable t);
public abstract boolean isDebugEnabled();
public abstract boolean isInfoEnabled();
public abstract boolean isWarnEnabled();
public abstract boolean isErrorEnabled();
public abstract boolean isFatalEnabled();
public static Logger getLogger(String category) {
if (categoryPrefix.length() != 0) {
category = categoryPrefix + category;
}
synchronized (loggersByCategory) {
Logger logger = (Logger) loggersByCategory.get(category);
if (logger == null) {
ensureLoggerFactorySet(false);
logger = loggerFactory.getLogger(category);
loggersByCategory.put(category, logger);
}
return logger;
}
}
private static void ensureLoggerFactorySet(boolean onlyIfCanBeSetFromSysProp) {
if (loggerFactory != null) return;
synchronized (Logger.class) {
if (loggerFactory != null) return;
String sysPropVal = getSystemProperty(SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY);
final int libraryEnum;
if (sysPropVal != null) {
sysPropVal = sysPropVal.trim();
boolean foundMatch = false;
int matchedEnum = MIN_LIBRARY_ENUM;
do {
if (sysPropVal.equalsIgnoreCase(getLibraryName(matchedEnum))) {
foundMatch = true;
} else {
matchedEnum++;
}
} while (matchedEnum <= MAX_LIBRARY_ENUM && !foundMatch);
if (!foundMatch) {
logWarnInLogger("Ignored invalid "" + SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY
+ "" system property value: "" + sysPropVal + """);
if (onlyIfCanBeSetFromSysProp) return;
}
libraryEnum = foundMatch ? matchedEnum : LIBRARY_AUTO;
} else {
if (onlyIfCanBeSetFromSysProp) return;
libraryEnum = LIBRARY_AUTO;
}
try {
setLibrary(libraryEnum);
if (sysPropVal != null) {
initializedFromSystemProperty = true;
}
} catch (Throwable e) {
final boolean disableLogging = !(onlyIfCanBeSetFromSysProp && sysPropVal != null);
logErrorInLogger(
"Couldn't set up logger for "" + getLibraryName(libraryEnum) + """
+ (disableLogging ? "; logging disabled" : "."), e);
if (disableLogging) {
try {
setLibrary(LIBRARY_NONE);
} catch (ClassNotFoundException e2) {
throw new RuntimeException("Bug", e2);
}
}
}
}
}
private static LoggerFactory createLoggerFactory(int libraryEnum) throws ClassNotFoundException {
if (libraryEnum == LIBRARY_AUTO) {
for (int libraryEnumToTry = MAX_LIBRARY_ENUM; libraryEnumToTry >= MIN_LIBRARY_ENUM; libraryEnumToTry--) {
if (!isAutoDetected(libraryEnumToTry)) continue;
if (libraryEnumToTry == LIBRARY_LOG4J && hasLog4LibraryThatDelegatesToWorkingSLF4J()) {
libraryEnumToTry = LIBRARY_SLF4J;
}
try {
return createLoggerFactoryForNonAuto(libraryEnumToTry);
} catch (ClassNotFoundException e) {
// Expected, intentionally suppressed.
} catch (Throwable e) {
logErrorInLogger(
"Unexpected error when initializing logging for ""
+ getLibraryName(libraryEnumToTry) + "".",
e);
}
}
logWarnInLogger("Auto detecton couldn't set up any logger libraries; FreeMarker logging suppressed.");
return new _NullLoggerFactory();
} else {
return createLoggerFactoryForNonAuto(libraryEnum);
}
}
private static LoggerFactory createLoggerFactoryForNonAuto(int libraryEnum) throws ClassNotFoundException {
final String availabilityCheckClassName = getAvailabilityCheckClassName(libraryEnum);
if (availabilityCheckClassName != null) { // Dynamically created factory
Class.forName(availabilityCheckClassName);
String libraryName = getLibraryName(libraryEnum);
try {
return (LoggerFactory) Class.forName(
"freemarker.log._" + libraryName + "LoggerFactory").newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unexpected error when creating logger factory for "" + libraryName + "".", e);
}
} else { // Non-dynamically created factory
if (libraryEnum == LIBRARY_JAVA) {
return new _JULLoggerFactory();
} else if (libraryEnum == LIBRARY_NONE) {
return new _NullLoggerFactory();
} else {
throw new RuntimeException("Bug");
}
}
}
private static boolean hasLog4LibraryThatDelegatesToWorkingSLF4J() {
try {
Class.forName(getAvailabilityCheckClassName(LIBRARY_LOG4J));
Class.forName(getAvailabilityCheckClassName(LIBRARY_SLF4J));
} catch (Throwable e) {
return false;
}
try {
Class.forName(REAL_LOG4J_PRESENCE_CLASS);
return false;
} catch (ClassNotFoundException e) {
try {
Object r = Class.forName(LOG4J_OVER_SLF4J_TESTER_CLASS)
.getMethod("test", new Class[] {}).invoke(null);
return ((Boolean) r).booleanValue();
} catch (Throwable e2) {
return false;
}
}
}
private synchronized static void setLibrary(int libraryEnum) throws ClassNotFoundException {
loggerFactory = createLoggerFactory(libraryEnum);
Logger.libraryEnum = libraryEnum;
}
private static void logWarnInLogger(String message) {
logInLogger(false, message, null);
}
private static void logErrorInLogger(String message, Throwable exception) {
logInLogger(true, message, exception);
}
private static void logInLogger(boolean error, String message, Throwable exception) {
boolean canUseRealLogger;
synchronized (Logger.class) {
canUseRealLogger = loggerFactory != null && !(loggerFactory instanceof _NullLoggerFactory);
}
if (canUseRealLogger) {
try {
final Logger logger = Logger.getLogger("freemarker.logger");
if (error) {
logger.error(message);
} else {
logger.warn(message);
}
} catch (Throwable e) {
canUseRealLogger = false;
}
}
if (!canUseRealLogger) {
System.err.println((error ? "ERROR" : "WARN") + " "
+ LoggerFactory.class.getName() + ": " + message);
if (exception != null) {
System.err.println("tException: " + tryToString(exception));
while (exception.getCause() != null) {
exception = exception.getCause();
System.err.println("tCaused by: " + tryToString(exception));
}
}
}
}
private static String getSystemProperty(final String key) {
try {
return (String) AccessController.doPrivileged(
new PrivilegedAction() {
@Override
public Object run() {
return System.getProperty(key, null);
}
});
} catch (AccessControlException e) {
logWarnInLogger("Insufficient permissions to read system property "" + key + "".");
return null;
} catch (Throwable e) {
logErrorInLogger("Failed to read system property "" + key + "".", e);
return null;
}
}
private static String tryToString(Object object) {
if (object == null) return null;
try {
return object.toString();
} catch (Throwable e) {
return object.getClass().getName();
}
}
}
源码分析
getLibraryName()方法主要是获取libraryEum做对应的LibraryName的名字并且以字符串的形式返回;
isAutoDetected()方法主要是检查libraryEum所对应,只要与四个其中的一个可以对应上,就会返回一个FALSE,证明可以匹配。
private static String getLibraryName(int libraryEnum) {
if (libraryEnum == LIBRARY_AUTO) {
return LIBRARY_NAME_AUTO;
}
if (libraryEnum == LIBRARY_NONE) {
return LIBRARY_NAME_NONE;
}
return LIBRARIES_BY_PRIORITY[(libraryEnum - 1) * 2 + 1];
}
private static boolean isAutoDetected(int libraryEnum) {
// 2.4: Remove libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS
return !(libraryEnum == LIBRARY_AUTO || libraryEnum == LIBRARY_NONE
|| libraryEnum == LIBRARY_SLF4J || libraryEnum == LIBRARY_COMMONS);
}
selectLoogerLibrary()用于选择LoggerLibrary通过LibraryEnum的编号进行查找,如果查找不到则会返回一个Exception
public static void selectLoggerLibrary(int libraryEnum) throws ClassNotFoundException {
if (libraryEnum < MIN_LIBRARY_ENUM || libraryEnum > MAX_LIBRARY_ENUM) {
throw new IllegalArgumentException("Library enum value out of range");
}
synchronized (Logger.class) {
final boolean loggerFactoryWasAlreadySet = loggerFactory != null;
if (!loggerFactoryWasAlreadySet || libraryEnum != Logger.libraryEnum) {
// Creates the factory only if it can be done based on system property:
ensureLoggerFactorySet(true);
// The system property has precedence because this method was deprecated by it:
if (!initializedFromSystemProperty || loggerFactory == null) {
int replacedLibraryEnum = Logger.libraryEnum;
setLibrary(libraryEnum);
loggersByCategory.clear();
if (loggerFactoryWasAlreadySet) {
logWarnInLogger("Logger library was already set earlier to ""
+ getLibraryName(replacedLibraryEnum) + ""; "
+ "change to "" + getLibraryName(libraryEnum) + "" won't effect loggers created "
+ "earlier.");
}
} else if (libraryEnum != Logger.libraryEnum) {
logWarnInLogger("Ignored " + Logger.class.getName() + ".selectLoggerLibrary(""
+ getLibraryName(libraryEnum)
+ "") call, because the "" + SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY
+ "" system property is set to "" + getLibraryName(Logger.libraryEnum) + "".");
}
}
}
}
createLoggerFactory()主要是确定选择哪一个LoggerFactory,然后去调用之实现的各种LoggerFactory 去生产Logger实例。
private static LoggerFactory createLoggerFactory(int libraryEnum) throws ClassNotFoundException {
if (libraryEnum == LIBRARY_AUTO) {
for (int libraryEnumToTry = MAX_LIBRARY_ENUM; libraryEnumToTry >= MIN_LIBRARY_ENUM; libraryEnumToTry--) {
if (!isAutoDetected(libraryEnumToTry)) continue;
if (libraryEnumToTry == LIBRARY_LOG4J && hasLog4LibraryThatDelegatesToWorkingSLF4J()) {
libraryEnumToTry = LIBRARY_SLF4J;
}
try {
return createLoggerFactoryForNonAuto(libraryEnumToTry);
} catch (ClassNotFoundException e) {
// Expected, intentionally suppressed.
} catch (Throwable e) {
logErrorInLogger(
"Unexpected error when initializing logging for ""
+ getLibraryName(libraryEnumToTry) + "".",
e);
}
}
logWarnInLogger("Auto detecton couldn't set up any logger libraries; FreeMarker logging suppressed.");
return new _NullLoggerFactory();
} else {
return createLoggerFactoryForNonAuto(libraryEnum);
}
}
lodInLogger()方法用于捕捉并处理出现的错误,并且打印出来程序执行错误的原因。
private static void logInLogger(boolean error, String message, Throwable exception) {
boolean canUseRealLogger;
synchronized (Logger.class) {
canUseRealLogger = loggerFactory != null && !(loggerFactory instanceof _NullLoggerFactory);
}
if (canUseRealLogger) {
try {
final Logger logger = Logger.getLogger("freemarker.logger");
if (error) {
logger.error(message);
} else {
logger.warn(message);
}
} catch (Throwable e) {
canUseRealLogger = false;
}
}
if (!canUseRealLogger) {
System.err.println((error ? "ERROR" : "WARN") + " "
+ LoggerFactory.class.getName() + ": " + message);
if (exception != null) {
System.err.println("tException: " + tryToString(exception));
while (exception.getCause() != null) {
exception = exception.getCause();
System.err.println("tCaused by: " + tryToString(exception));
}
}
}
}
打印信息
private static String tryToString(Object object) {
if (object == null) return null;
try {
return object.toString();
} catch (Throwable e) {
return object.getClass().getName();
}
}



