理清Java日志体系

原创
2016/11/01 15:57
阅读数 586

0.总体介绍

日志体系由三部分组成

  • 日志门面接口
  • 一系列绑定和桥接
  • 具体的日志实现

所在的位置,如下图所示:

image

1.日志实现框架

  • log4j 最广泛应用的日志框架,成为事实上的标准
  • jul(java.util.logging) jdk1.4加入,为了对抗log4j,效率灵活性较差使用较少
  • logback 基于slf4j-api接口实现,性能高于log4j
  • log4j2 重写了log4j,性能高于log4j,logback
  • 其他

注:log4j、logback、log4j2是同一个作者Ceki Gülcü

2.日志门面接口JCL和SLF4J

上面介绍了四种日志框架,到底用哪个日志框架,现在广泛应用的还是log4j,如果负载较高可以考虑使用logback和log4j2.

但是如果两个系统相互依赖,用的不同的日志框架,难道需要依赖两个日志框架么?

Apache和log4j的作者提供两种接口层面的汇总

  • JCL(commons-logging)
  • SLF4J(simple log facade for java)两个日志框架的门面。

提供了统一的日志抽象接口,适配和转接了各种日志框架,使用者只用调用抽象层统一的接口就行了。应用层不直接依赖实际的日志实现。

但是,问题又来了,怎么使用呢?

  • 问题一:我的项目中准备使用SLF4J作为接口层面统一,使用logback 作为日志实现框架,但是我依赖了一些开源框架使用了log4j,或者JCL(commons-logging),那么怎么汇总?
  • 我的项目中已经使用了log4j,但是依赖了一些开源框架使用了SLF4J,那么怎么转接SLF4J的实现到log4j呢?

这里拿SLF4J举例,JCL(commons-logging)同样适合场景。

3.桥接

问题一,先看一幅图

image

  • 项目中打算使用SLF4J作为接口层,使用logback作为实现层
  • 项目依赖的开源框架使用了Commons-logging,log4j,juc日志框架
  • 使用jcl-over-slf4j桥接commons-logging
  • 使用log4j-over-slf4j桥接log4j
  • 使用jul-to-slf4j桥接jul(java.util.logging)

那么什么是桥接?

桥接的原理是把对应的门面日志接口重新实现了一遍,包名、类名、接口都一样,只是具体实现它委托给SLF4J了。

通过一系列桥接,它们把已存在的日志门面适配到SLF4J(jul-to-slf4j)。或者仿效已存在的日志门面或者实现(jcl-over-slf4j,log4j-over-slf4j,jul-to-slf4j)。

总结:

  • 比如我们项目中依赖了spring-core,因为它原生依赖commons-logging,所以需要用jcl-over-slf4j桥接包来代替commons-logging把具体实现委托给slf4j
  • 项目中要排除掉commons-logging
  • 再依赖jcl-over-slf4j
  • jcl-over-slf4j和commons-logging拥有相同的包名、类名、接口,从而达到桥接的效果

4.绑定

再看问题二,再来一幅图

image

  • 项目中打算使用SLF4J作为接口层,使用log4j作为实现层(log4j并没有实现SLF4J接口)
  • 项目依赖的开源框架使用了Commons-logging,juc日志框架
  • 使用jcl-over-slf4j桥接commons-logging
  • 使用jul-to-slf4j桥接jul(java.util.logging)
  • slf4j-api绑定到slf4j-log412。基于一个已存在的日志框架来实现了SLF4J API

那么什么是绑定?

绑定的原理是因为slf4j-api中的LogFactory通过StaticLoggerBinder.getSingleton()获取具体实现logger,一个绑定包实现了org/slf4j/impl/StaticLoggerBinder.class,所以它们在编译时刻就绑定在一起,而绑定包中的StaticLoggerBinder类会绑定对应的实现。这部分看看源码就一目了然了。

5.总结&实现包附录

通过桥接和绑定就可以解决上述的问题。日志推荐使用做法是,使用SLF4J+logback,如果依赖了其他开源项目导致日志混乱,可以使用桥接的方式进行解决。

下面附录一下SLF4J桥接和绑定的包

SLF4J桥接

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

SLF4J绑定

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

参考文章

展开阅读全文
打赏
2
4 收藏
分享
加载中
更多评论
打赏
0 评论
4 收藏
2
分享
返回顶部
顶部