private static final Logger LOG = LoggerFactory.getLogger(Test.class);
LOG.error("exec error,msg={}", msg, e);
我們可以看到以上語句調(diào)用的是slf4j的這個(gè)方法:
void error(String var1, Object var2, Object var3);
參數(shù)里面并沒有Throwable類型的跨蟹,但是在實(shí)際運(yùn)行的時(shí)候是會打印堆棧的茅坛,那么為什么會打印堆棧呢?我們來看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);
}
當(dāng)throwable為null時(shí)惩激,extractThrowableAnRearrangeArguments這個(gè)方法的名字已經(jīng)寫得很清楚了,我們繼續(xù)往下看
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;
}
}
好了苞慢,關(guān)鍵就在這一句
return lastEntry instanceof Throwable ? (Throwable)lastEntry : null;
個(gè)人非常反對這種寫法emmm...大家不要學(xué)