在全局异常处理类中,有下面的一段代码,其中重点看 log.error() 方法:
(log的类型是 slf4j-api-1.7.36.jar 中的 org.slf4j.Logger类)
@ExceptionHandler(RuntimeException.class) public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生未知异常.", requestURI, e); return AjaxResult.error(e.getMessage()); }
我想要看看源码中对应的方法,找到3个方法比较相似:
/** * Log an exception (throwable) at the ERROR level with an * accompanying message. * * @param msg the message accompanying the exception * @param t the exception (throwable) to log */ public void error(String msg, Throwable t); /** * Log a message at the ERROR level according to the specified format * and arguments. * <p/> * <p>This form avoids superfluous object creation when the logger * is disabled for the ERROR level. </p> * * @param format the format string * @param arg1 the first argument * @param arg2 the second argument */ public void error(String format, Object arg1, Object arg2); /** * Log a message at the ERROR level according to the specified format * and arguments. * <p/> * <p>This form avoids superfluous string concatenation when the logger * is disabled for the ERROR level. However, this variant incurs the hidden * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method, * even if this logger is disabled for ERROR. The variants taking * {@link #error(String, Object) one} and {@link #error(String, Object, Object) two} * arguments exist solely in order to avoid this hidden cost.</p> * * @param format the format string * @param arguments a list of 3 or more arguments */ public void error(String format, Object... arguments);
但此处的 log.error("请求地址'{}',发生未知异常.", requestURI, e);
,看上去是归属于 public void error(String format, Object arg1, Throwable t);
这种方法签名类型,而该方法签名在源码中找不到,于是debug源码查看究竟,因为使用了 logback,所以实际使用了 org.slf4j.Logger 的实现类 ch.qos.logback.classic.Logger类,然后进一步debug源码,发现是属于该方法签名:public void error(String format, Object arg1, Object arg2);
。然后往深了debug,最终发现了它的实现方式:
拓展:
如果除format之外的arg参数大于2个,则是使用这个重载方法 public void error(String format, Object... arguments);
,则可能有超过3个的参数,则参数数组 argArray 由所有的 arguments 组成。
过程是类似的,但是要注意2点:
{}
,就从 argArray 数组中使用多少个arg拼接进去,如果argArray中还有多的未使用的arg,丢弃;如果 argArray 中的 arg不够,则会有一些 {}
,不被替换,导致拼接后的字符串中仍然保留这些 {}
。