logback不传throwable参数也会打印堆栈

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...大家不要学

你可能感兴趣的:(logback不传throwable参数也会打印堆栈)