SLF4J

Posted liyunfeng17

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SLF4J相关的知识,希望对你有一定的参考价值。

为什么要用SLF4J?

  • 代码中编写日志记录语句使用SLF4J的主要动机是让程序独立于任何特定的日志记录库,这些日志记录库可能需要与现在配置不同的配置,而且还会引入更多令人头疼的维护问题。
  • 然而除了这个之外,SLF4J API还有一个使用SLF4J而不是用长期感兴趣的 Log4j 更让人信服的功能,也就是占位符功能,在代码中用{}来表示。
  • 占位符功能与 String的format()方法中 的%s非常相似,因为它在运行时刻才提取所提供的真正的字符串。
  • 这不仅缩减了代码中的许多字符串连接,而且减少了创建String对象所需要的资源。
  • 即便在生产环境日志级别比如DEBUG和INFO级别的字符串连接可能不需要的时候,仍然可以起到同样的效果。
  • 由于 字符串是不可更改的 ,而且它们是在字符串池中创建的,这些字符串使用了 堆内存 ,当应用在生产环境中运行在ERROR级别的时候,字符串在大多数情况下就不是必须的,比如DEBUG语句里的字符串就不是必须的。
  • 通过使用SLF4J,你可以延迟字符串的创建到运行时刻,这意味着只有在需要字符串的时候才创建它。
  • 如果你已经使用了log4j,那么你已经熟悉把调试语句放入if()条件内的工作场景,而SLF4J占位符功能比log4j更适合这种场景。

用Log4j时的做法:

  

if (logger.isDebugEnabled()) {

    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

}

使用SLF4J,更简洁的格式达到同样的效果,如下:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

在SLF4J中,我们不需要进行字符串拼接,不会导致使用临时字符串带来的消耗。

相反,我们使用带占位符的模板消息来记录日志信息,并提供实际值作为参数。

也许你会想,要是有多个参数该怎么办,你可以使用带参数版的日志方法,也可以通过Object数组传入。

在为日志信息产生最终的字符串之前,该方法会检查是否开启了特定的日志级别,这不仅降低了内存占用,而且预先减少了执行字符串拼接所消耗的CPU时间。

下面的SLF4J日志方法的代码,来自于slf4j-log4j12-1.6.1.jar包里的Log4j的适配器类Log4jLoggerAdapter。

  

public void debug(String format, Object arg1, Object arg2) { if (logger.isDebugEnabled()) {

      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);

      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());

    }

}

选择SLF4J而不是直接选用Log4j, commons logging, logback 或者 java.util.logging。主要有以下原因?

  1. 在开源库或者私有库中使用SLF4J,可以使它独立于任何的日志实现,不需要管理多个库和多个日志文件。
  2. SLF4J提供了占位日志记录,通过移除对isDebugEnabled(), isInfoEnabled()的检查提高了代码的可读性。
  3. 通过使用日志记录方法,直到你使用到的时候,才会去构造日志信息(字符串),这就同时提高了内存和CPU的使用率。
  4. 越少的临时字符串,垃圾回收器就意味着越少的工作,这就意味着为应用程序提供更好的吞吐量和性能。

总结:在java中任何新的代码开发,都应使用SLF4J而不是任何的日志API,包括log4J。

以上是关于SLF4J的主要内容,如果未能解决你的问题,请参考以下文章

@Slf4j注解的使用

slf4j

slf4j的使用规范

日志框架之日志门面SLF4J的使用

slf4j+log4j配置

SLF4J + logback 实现日志输出和记录