private static final Logger LOG = LoggerFactory.getLogger(Test.class);
LOG.error("exec error,msg={}", msg, e);
我们可以看到以上语句调用的是slf4j的这个方法:
void error(String var1, Object var2, Object var3);
参数里面并没有Throwable类型的,但是在实际运行的时候是会打印堆栈的,那么为什么会打印堆栈呢?我们来看logback的源码:
public void error(String format, Object arg1, Object arg2) {
this.filterAndLog_2(FQCN, (Marker)null, Level.ERROR, format, arg1, arg2, (Throwable)null);
}
private void filterAndLog_2(String localFQCN, Marker marker, Level level, String msg, Object param1, Object param2, Throwable t) {
FilterReply decision = this.loggerContext.getTurboFilterChainDecision_2(marker, this, level, msg, param1, param2, t);
if (decision == FilterReply.NEUTRAL) {
if (this.effectiveLevelInt > level.levelInt) {
return;
}
} else if (decision == FilterReply.DENY) {
return;
}
this.buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[]{param1, param2}, t);
}
private void buildLoggingEventAndAppend(String localFQCN, Marker marker, Level level, String msg, Object[] params, Throwable t) {
LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params);
le.setMarker(marker);
this.callAppenders(le);
}
public LoggingEvent(String fqcn, Logger logger, Level level, String message, Throwable throwable, Object[] argArray) {
this.fqnOfLoggerClass = fqcn;
this.loggerName = logger.getName();
this.loggerContext = logger.getLoggerContext();
this.loggerContextVO = this.loggerContext.getLoggerContextRemoteView();
this.level = level;
this.message = message;
this.argumentArray = argArray;
if (throwable == null) {
throwable = this.extractThrowableAnRearrangeArguments(argArray);
}
if (throwable != null) {
this.throwableProxy = new ThrowableProxy(throwable);
LoggerContext lc = logger.getLoggerContext();
if (lc.isPackagingDataEnabled()) {
this.throwableProxy.calculatePackagingData();
}
}
this.timeStamp = System.currentTimeMillis();
}
追到这里,我们看到这样一段代码
if (throwable == null) {
throwable = this.extractThrowableAnRearrangeArguments(argArray);
}
当throwable为null时,extractThrowableAnRearrangeArguments这个方法的名字已经写得很清楚了,我们继续往下看
private Throwable extractThrowableAnRearrangeArguments(Object[] argArray) {
Throwable extractedThrowable = EventArgUtil.extractThrowable(argArray);
if (EventArgUtil.successfulExtraction(extractedThrowable)) {
this.argumentArray = EventArgUtil.trimmedCopy(argArray);
}
return extractedThrowable;
}
public static final Throwable extractThrowable(Object[] argArray) {
if (argArray != null && argArray.length != 0) {
Object lastEntry = argArray[argArray.length - 1];
return lastEntry instanceof Throwable ? (Throwable)lastEntry : null;
} else {
return null;
}
}
好了,关键就在这一句
return lastEntry instanceof Throwable ? (Throwable)lastEntry : null;
个人非常反对这种写法emmm...大家不要学