Java日志系统相关工具梳理

日志系统实现工具

java.util.logging(jul)

JDK中实现的日志系统。

log4j

最早得到广泛使用的日志系统。

logback

log4j的改良版本,比log4j拥有更多的特性,同时也带来很大性能提升。

logback分为3个组件,logback-core, logback-classic 和 logback-access。
logback-core提供了logback的核心功能,是另外两个组件的基础。
logback-classic则实现了slf4j的API,所以当想配合slf4j使用时,则需要引入这个包。
logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口。

日志系统绑定工具

commons-logging(jcl)

Apache提供的日志系统绑定工具。jcl会在运行时动态绑定日志系统的实现类,用户只需要面向jcl的API进行开发。

slf4j

全称是The Simple Logging Facade for Java,是一个简单日志门面抽象框架。

slf4j会在程序启动时根据classpath中的日志系统实现(log4j, logback等)静态绑定日志系统的实现类,用户只需要面向slf4j的API进行开发,然后通过依赖配置来调整底层实际使用的日志系统实现类。

slf4j与实际日志系统的绑定

slf4j与实际日志系统进行绑定的依赖组件(Binding):

  • slf4j-jdk14: slf4j到jdk-logging的Binding
  • slf4j-log4j12: slf4j到log4j1的Binding
  • log4j-slf4j-impl: slf4j到log4j2的Binding
  • logback-classic: slf4j到logback的Binding
  • slf4j-jcl: slf4j到commons-logging的Binding

PS: 上面的这些Binding在classpath中只能存在一个,如果有多个则会在程序启动时导致slf4j静态绑定失败。

其他日志系统API转到slf4j的桥接器

如果应用程序已经用了其他日志系统的API来进行开发(或应用程序的依赖中使用了其他日志系统的API),想在不修改程序代码的情况下将日志输出重定向到slf4j,就需要引入桥接器。

常用的桥接器有这些:

  • jul-to-slf4j: jdk-logging到slf4j的桥接器
  • log4j-over-slf4j: log4j1到slf4j的桥接器
  • jcl-over-slf4j: commons-logging到slf4j的桥接器

例如我们开发的某个应用程序原本使用的是log4j来进行日志输出的,代码中也是用的log4j的API,现在想在不修改程序代码的基础上将日志系统转为使用logback,则只需要去掉原先的log4j依赖,然后加入slf4j-api、logback-classic、log4j-over-slf4j依赖。这样log4j的实现类实际上被桥接器log4j-over-slf4j替换掉了,其真正的实现是将log4j的日志输出重定向到了slf4j,而slf4j又绑定到了logback,所以日志系统就被切换过来了。

PS: 日志系统的Binding组件和桥接器有一些是冲突的,原因很好理解,举例说明:如果同时在应用程序中加入依赖slf4j-log4j12和log4j-over-slf4j,则slf4j会将日志输出绑定到log4j,而log4j又会把皮球踢还给slf4j,于是便会形成死循环。在理解了Binding组件和桥接器后,这些冲突的原因也能很快理解,在使用时就不会出错而不知道如何解决了。