log.info是怎么实现?

842 阅读2分钟

引入:

小菜鸟因为总是用sout输出调试信息被组长批评,于是写下了这样一行代码:

log.info("我"+UserUtils.getName()+"不是小菜鸟!",);

小菜鸟心想,也没什么了不起嘛!sout换了个名字输出而已!

于是心满意足的小菜鸟开始浏览其他同事的日志:

log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);

小菜鸟 感到很好奇,好像同事的输出更加规范,也不用想在哪使用 "+" 拼接了,很不错嘛!

于是他开始思考起了如何实现这个功能。。。。。。

==> ==> ==> ==> ==> ==> ==>0% ==> 99% ==> 99% ==> 99%

实现:

一天过去了,小菜鸟实现了99%,还有一窍未通

为了怕组长发现他摸鱼 于是他决定看一下源码是怎么实现的!

MessageFormatter

public static final FormattingTuple arrayFormat(String messagePattern, Object[] argArray) {
    Throwable throwableCandidate = getThrowableCandidate(argArray);
    Object[] args = argArray;
    if (throwableCandidate != null) {
        args = trimmedCopy(argArray);
    }

    return arrayFormat(messagePattern, args, throwableCandidate);
}

SL4J依赖于内部的MessageFormatter来实现,通过接收参数列表的形式,最后一个参数可以使Excepition

处理最后一个参数:

public static Throwable getThrowableCandidate(Object[] argArray) {
    if (argArray != null && argArray.length != 0) {
        Object lastEntry = argArray[argArray.length - 1];
        return lastEntry instanceof Throwable ? (Throwable)lastEntry : null;
    } else {
        return null;
    }
}

处理参数数据和模板消息为空的情况:

if (messagePattern == null) {
    return new FormattingTuple((String)null, argArray, throwable);
} else if (argArray == null) {
    return new FormattingTuple(messagePattern);
}

根据参数数组argArray遍历追加内容到模板messagePattern,每找到一个"{}" 就把检查开始的位置 i 向后移动

for(int L = 0; L < argArray.length; ++L) {
    int j = messagePattern.indexOf("{}", i);
    if (j == -1) {
        if (i == 0) {
            return new FormattingTuple(messagePattern, argArray, throwable);
        }

        sbuf.append(messagePattern, i, messagePattern.length());
        return new FormattingTuple(sbuf.toString(), argArray, throwable);
    }

处理字符串转义的情况;

if (isEscapedDelimeter(messagePattern, j)) {
        if (!isDoubleEscaped(messagePattern, j)) {
            --L;
            sbuf.append(messagePattern, i, j - 1);
            sbuf.append('{');
            i = j + 1;
        } else {
            sbuf.append(messagePattern, i, j - 1);
            deeplyAppendParameter(sbuf, argArray[L], new HashMap());
            i = j + 2;
        }
    } else {
        sbuf.append(messagePattern, i, j);
        deeplyAppendParameter(sbuf, argArray[L], new HashMap());
        i = j + 2;
    }
}

结局:

看了看源码的实现,小菜鸟觉得和自己平常写业务也差不太多,感觉自己又学到了

看了看时间,六点半,完美!一套连招,小菜鸟愉快下班!