【Java日志】Log4j, SLF4J, Logback, Log4J2,有啥区别?如何选择?

883 阅读4分钟

参考:www.youtube.com/watch?v=SWH…

今天无意中点开一个视频,看了个开头就觉得很好笑。 对于不同的程序员来说,可能有很多“Hell”,比如:Callback Hell, Inheritance(继承) Hell, Expeptions Hell...

但有一个“Hell”只会在同一种语言中出现,那就是Java世界中的Logging Hell。

谈到Java的logging,相信很多小伙伴都会会心一笑(苦笑)...

1. 进化史

1.1 JDK提供的logger

最早的JDK 1.4也提供了Logging的包,即:java.util.logging

  • 在这个包下有个类叫Logger,getLogger(className)。
  • JDK也分了log levels,叫:info, severe, fine。
  • 也有Message Handler:console, file。

但是好用吗?当然不。 --> 不然也没上述这些日志框架的事儿了。比如有:

  • performance方面的问题。
  • 没有那么灵活。
  • 或者功能不够...
1.2 Log4J的诞生

因为有打印日志的需求,而JDK提供的功能有局限性,那么Java开源类库就此诞生。

最最有名的就是Log4J:

  • org.apache.log4j.Logger,和JDK原生的差不多,也是通过传入类名。
  • 也提供了log levels:debug, error, info...
  • Log Appenders:File / Console / Rolling File (daily) / JDBC / SMTP / JMS...
  • Formating options:多种格式可自定义。
1.3 Slf4J的诞生

虽然Log4J很强大,也很好用,但是依然有代码用着另外一些log框架,如JDK Util的,或是其它第三方类库的。我们在代码中不得不做各种转换。

这时候自然而然的会想到一个设计模式————外观模式(Facade模式)。而Slf4J就是这样的一个类库!

即: 我们的代码(使用的是facade lib APIs) --> Facade Lib --> Actual Logiing Lib

进一步: 我们的代码 --> Slf4J --> Log4J / JDK

也就是Slf4J只是统一了接口,而真正做日志存储的依旧是Log4J或是JDK自带的logging。

Slf4J变的很流行之后,很多Logging框架都会带上Slf4J的wapper,让我们不用再额外引入Sjf4J的包。

image.png

1.4 当下最流行的两个Logging类库
  • Logback
  • Log4j2

它们都参照了Log4J成功的部分,以及修复了Log4J不足的部分(如performance),当然他们都支持了Slf4J,以便我们在自己的代码中依然使用的是Sjf4J的接口。

2. 一些建议

2.1 总是使用Slf4J作为facade API

原因是假如我们自己的程序使用的是Log4J2,而我们引入的其它的第三方类库(如Spring boot框架,使用的是Logback),那么势必要在我们的程序中引入以上两个依赖。

但如果大家都统一使用的是Slf4J,那么就好办了!只需要引入自己想使用的实现即可。

2.2 选择哪个Logging框架?
  • 不要选择Log4J,因为这个项目已经没有在维护了。
  • 选择Logback或是Log4J2中的一个。
    • 可以使用Logback,因为当下看起来它更流行。还有一个原因是因为它是由最初设计Log4J的人设计的!!(这个人也设计了Slf4J)。
    • 但是Log4J2有额外的一些Logback没有的功能,如Lazy loading messages / Async logging等功能。如果需要使用这些功能,那么可以选择Log4J2。

3. Spring boot中的Logging

作为Java语言中流行的框架,Spring boot使用的是Slf4J作为日志接口,所以理论上我们可以使用任一一个logging实现。

具体查看官网(这里引用的是2.7.2版本): docs.spring.io/spring-boot…

By default, if you use the “Starters”, Logback is used for logging. Appropriate Logback routing is also included to ensure that dependent libraries that use Java Util Logging, Commons Logging, Log4J, or SLF4J all work correctly.

这里指的是我们使用的是starter,如spring-boot-starter-logging,(不需要特别的引入这个依赖,因为spring-boot-starter-web会帮忙引入)。Logback作为默认的日志实现框架。

另外,Spring boot文档专门指出: image.png

如果使用的是Spring boot,并不需要特地的更换logging依赖,Spring boot的默认配置就能work。

4. 另外的一些桥接类库

比如:

  • log4j-to-slf4j.jar
  • jul-to-slf4j.jar
  • 等等...

image.png

log4j-to-slf4j.jar,即Log4j 2 to SLF4J Adapter,官网:logging.apache.org/log4j/log4j…

主要的作用是将项目中的直接使用Log4J2日志类,转为Slf4J。 --> 如果大家都遵守面向facade api编程(使用Slf4J作为接口),那么理论上就没这些桥接类库什么事了!!!

桥接类库有很多很多,但如果使用的是Spring boot,那么如同#3中说的,直接使用默认的就完事儿了!!!