常见的日志框架
- log4j
- log4j2
- logback
- java util logging(简写为JUL)
log4j
在JDK 1.3及以前,Java打日志依赖System.out.println(), System.err.println()或者e.printStackTrace(),Debug日志被写到STDOUT流,错误日志被写到STDERR流。这样打日志有一个非常大的缺陷,即无法定制化,且日志粒度不够细。log4j是在这样的环境下诞生的,它是一个里程碑式的框架,它定义的Logger、Appender、Level等概念如今已经被广泛使用。
log4j可以当之无愧地说是Java日志框架的元老,1999年发布首个版本,2012年发布最后一个版本,2015年正式宣布终止,至今还有无数的系统在使用log4j,甚至很多新系统的日志框架选型仍在选择log4j。
在log4j被Apache Foundation收入门下之后,由于理念不合,log4j的作者Ceki离开并开发了slf4j和logback。
log4j2
Apache Logging一直在关门憋大招,log4j2在beta版鼓捣了几年,终于在2014年发布了GA版,不仅吸收了logback的先进功能,更通过优秀的锁机制、LMAX Disruptor、"无垃圾"机制等先进特性,在性能上全面超越了log4j和logback。
java util logging
受Log4j启发,Sun在Java1.4版本中引入了java.util.logging,但是j.u.l功能远不如log4j完善,开发者需要自己编写Appenders(Sun称之为Handlers),且只有两个Handlers可用(Console和File),j.u.l在Java1.5以后性能和可用性才有所提升。
logback
logback和log4j是同一个作者创作,它是log4j的升级版,因此logback相较于log4j有更多的优点:
- 原生实现了SLF4J API(log4j需要一个中间层转换)
- 支持XML、Groovy方式配置
遇到的问题
如上所述,java的日志框架种类繁多,不同的日志框架需要不同的配置。
加入项目A中使用log4j做为日志框架,而依赖的第三方库(假如说是guava)使用jul做为日志框架,那么,项目A不仅要有log4j的配置,还需要有jul的配置。
如果其他类库又使用了其他日志框架呢?
诸如此类的问题会是无休无尽?
怎么办?这时候就需要使用日志门面了。
所谓日志门面,如常用的slf4j,并不是日志框架。而是只提供简单的日志api。所有的工程和类库都是用slf4j的话,就不会有任何兼容问题。
那么,既然日志门面不是日志框架,日志具体由谁来输出呢?还是由上面所列的日志框架输出。日志门面和日志框架之间通过相应的api进行桥接。
这样,任何第三方类库,只要使用了slf4j来输出日志,由于没有指定具体的日志框架,因此使用方可以自行选取任何日志框架,都可以正确输出日志。
日志门面
- commons-logging
- slf4j
commons-logging
commons-logging不是一个日志打印框架,而是一个API bridge,开发者可以使用它兼容不同的日志框架(log4j和j.u.l)。然而,commons-logging对Log4j和j.u.l的配置问题兼容的并不好,使用commons-loggings还可能会遇到类加载问题,导致NoClassDefFoundError的错误出现。
slf4j
slf4j是一个“日志门面”(Logging Facade),而不是一个完整的日志框架。它提供了一套记录日志的api,但不提供输出日志的功能,而是通过对接如log4j、java.util.logging等日志框架,来实现日志的输出。
log4j的创始人Ceki发起了SLF4J(Simple Logging Facade for Java)项目,从设计模式的角度说,它是用来在log和代码层之间起到门面作用,对于用户来说只要使用SLF4J提供的接口,即可隐藏日志的具体实现,SLF4J提供的核心API是一些接口和一个LoggerFactory的工厂类,用户只需按照它提供的统一纪录日志接口,最终日志的格式、纪录级别、输出方式等可通过具体日志系统的配置来实现,因此可以灵活的切换日志系统
slf4j与常见日志框架的桥接
image.png- log4j(log4j1)的桥接器:
slf4j-log4j12
- log4j2的桥接器:
log4j-slf4j-impl
- jul的桥接器:
slf4j-jdk14
- logback天然与slf4j适配,不需要额外引入适配库(毕竟是一个作者写的)
网友评论