java日志框架梳理(slf4j,log4j,logback,jcl,jul)

提到java日志,就会想到log4j,slf4j,logback,commons-logging,java.util.logging等一连串名字,pom文件里引用了一堆依赖,但并不清楚它们的原理。

概述

  • Log4j Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。
  • Log4j2 Apache Log4j 2是apache开发的一款Log4j的升级产品。
  • Commons Logging Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging。
  • Slf4j 类似于Commons Logging,是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)。
  • Logback 一套日志组件的实现(slf4j阵营)。
  • Jul (Java Util Logging),自Java1.4以来的官方日志实现。

    历史

    http://ieye.iteye.com/blog/1924215

    最先出现的是apache开源社区的log4j,这个日志确实是应用最广泛的日志工具,成为了java日志的事实上的标准。然而,当时Sun公司在jdk1.4中增加了JUL日志实现,企图对抗log4j,但是却造成了混乱,这个也是被人诟病的一点。当然也有其他日志工具的出现,这样必然造成开发者的混乱,因为这些日志系统互相没有关联,替换和统一也就变成了比较棘手的一件事。想象下你的应用使用log4j,然后使用了一个其他团队的库,他们使用了JUL,你的应用就得使用两个日志系统了,然后又有第二个库出现了,使用了simplelog。这个时候估计让你崩溃了,这是要闹哪样?这个状况交给你来想想办法,你该如何解决呢?进行抽象,抽象出一个接口层,对每个日志实现都适配或者转接,这样这些提供给别人的库都直接使用抽象层即可。不错,开源社区提供了commons-logging抽象,被称为JCL,也就是日志框架了,确实出色地完成了兼容主流的日志实现(log4j、JUL、simplelog),基本一统江湖,就连顶顶大名的spring也是依赖了JCL。看起来事物确实是美好,但是美好的日子不长,接下来另一个优秀的日志框架slf4j的加入导致了更加混乱的场面。比较巧的是slf4j的作者(Ceki Gülcü)就是log4j的作者,他觉得JCL不够优秀,所以他要自己搞一套更优雅的出来,于是slf4j日志体系诞生了,并为slf4j实现了一个亲子——logback,确实更加优雅,但是由于之前很多代码库已经使用JCL,虽然出现slf4j和JCL之间的桥接转换,但是集成的时候问题依然多多,对很多新手来说确实会很懊恼,因为比单独的log4j时代“复杂”多了,可以关注下这个,抱怨声确实很多。到此本来应该完了,但是Ceki Gülcü觉得还是得回头拯救下自己的“大阿哥”——log4j,于是log4j2诞生了,同样log4j2也参与到了slf4j日志体系中,想必将来会更加混乱。

经过一番整合和厮杀,现在Java日志领域分成两大阵营:JCL和Slf4j,JCL用户基数大,但Slf4j后来居上,用户群体逐步上升,现在公司采用的就是Slf4j。

JCL

既然日志框架层出不穷,当系统产生依赖时,日志就会出现问题,无法管理,因此,Apache推出了Jakarta Commons Logging,JCL只是定义了一套日志接口(其内部也提供一个Simple Log的简单实现),通过门面模式对外提供一个统一的调用接口,屏蔽子系统之间复杂的调用关系,对客户端来讲,使用起来更容易。
支持运行时动态加载日志组件的实现,也就是说,在你应用代码里,只需调用Commons Logging的接口,底层实现可以是log4j,也可以是Java Util Logging。 使用JCL一般(如果是log4j可以不需要)需要一个配置commons-logging.properties在classpath上,这个文件有一行代码:

org.apache.commons.logging.LogFactory= org.apache.commons.logging.impl.LogFactoryImpl

这个是告诉JCL使用哪个日志实现,JCL会在classpath下去加载对应的日志工厂实现类,具体的日志工厂实现类可以是log4j实现,可以是jul实现等等。用户只需要依赖JCL的api即可,对日志系统的替换只需要修改下commons-logging.properties文件切换到对应的日志工厂实现即可。但是我们也可以看到因为JCL是运行时去加载classpath下的实现类,会有classloader问题。而且因为log4j尚不支持参数占位符打日志的方式,所以JCL也会更加无力。

SLF4J

SLF4j是Simple Logging Facade for Java的简称,即java的简单日志门面。作者Ceki Gülcü先后创建了slf4j(日志门面接口,类似于Commons Logging)和Logback(Slf4j的实现)两个项目,并回瑞典创建了QOS公司,QOS官网上是这样描述Logback的:The Generic,Reliable Fast&Flexible Logging Framework(一个通用,可靠,快速且灵活的日志框架)。
类似于Apache Common-Logging,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。
对比JCL和SLF4J,SLF4J实现更优秀:

  • JCL是运行时去加载classpath下的实现类,会有classloader问题。
  • SLF4J是编译时绑定到具体的日志框架,性能优于采用运行时搜寻的方式的JCL
  • JCL性能开销更高,为了减少构建日志信息的开销,代码冗余,SLF4J的官方示例:
    if(logger.isDebugEnabled()) {
    logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    }
    

    而使用SLF4J,只需要:

    logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    

    也就是说,slf4j把构建日志的开销放在了它确认需要显示这条日志之后,减少内存和cup的开销,使用占位符号,代码也更为简洁。

SLF4J桥接与适配
为了将JCL,Log4J,JUL的日志统一到slf4j的抽象层,分别定义了一组桥接器。按照官方描述:

Often, some of the components you depend on rely on a logging API other than SLF4J. You may also assume that these components will not switch to SLF4J in the immediate future. To deal with such circumstances, SLF4J ships with several bridging modules which redirect calls made to log4j, JCL and java.util.logging APIs to behave as if they were made to the SLF4J API instead.


分析这张图,通过引入jcl-over-slf4j.jar,log4j-over-slf4j.jar,jul-to-slf4j.jar,分别将原本JCL,log4j,jul的日志接口桥接到slf4j,然后通过一个适配层slf4j-log412.jar,slf4j-jdk14.jar提供具体的日志实现(logback不需要)。
详细说明参考官方文档:
https://www.slf4j.org/legacy.html

需要注意的问题


以上红色箭头代表互斥,可以看到,最终实现层只有一种,同时,也不需要将同一种日志系统实现经过slf4j桥接适配给自己。

性能对比

https://www.sitepoint.com/which-java-logging-framework-has-the-best-performance/
https://blog.takipi.com/the-logging-olympics-a-race-between-todays-top-5-logging-frameworks/

参考

https://www.cnblogs.com/chenhongliang/p/5312517.html
http://ieye.iteye.com/blog/1924215
http://blog.csdn.net/yycdaizi/article/details/8276265
https://www.cnblogs.com/chenhongliang/p/5312517.html

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @sxzhou Jan 3, 2018

奉献爱心