SLF4J与Logback、Log4j1、Log4j2、JCL、J.U.L是如何关联使用的

日志是Java程序员日常开发当中必须要接触的一个环节。Java的日志五花八门,有各种各样的实现,现在梳理一下Java日志相关的框架,及其使用使用细节。我们在日常使用过程中,主要会接触到SLF4J、Logback、Log4j1、Log4j2、JCL和J.U.L等日志框架。

对于日志框架的最佳实践,推荐使用使用Log Facade,而不是具体Log Implementation,即在代码中直接使用 Log4j-API 或者 SLF4J(不推荐继续使用 JCL)的类,而不推荐使用Log4j1,Log4j2,Logback或者J.U.L的类(配置文件当中配置好即可)。

Log4j-API/Log4j-core类似于SLF4J/Logback,在Log4j2的官方文档当中宣称比Logback性能高很多LINK,其实现方案类似于SLF4J/Logback,因此,在这里主要分析SLF4J与不同的日志框架的关联使用情况。

1. SLF4J承接不同的日志框架(日志框架—->SLF4J)

官方文档

当项目是使用多种日志API时,可以统一适配到SLF4J,中间使用SLF4J或者第三方提供的日志适配器适配到SLF4J,SLF4J再底层用开发者想用的一个日志框架来进行日志系统的实现,从而达到了多种日志的统一实现。其中的技术实现大体有一下两种方式:

  • 重写上游类的实现。比如jcl-over-slf4j和log4j-over-slf4j,为了承接log4j 1,重写了log4j 1 的Logger和LogFactory类。
  • 对接上游类的扩展方案。比如jul-to-slf4j和log4j-to-slf4j,为了承接J.U.L,实现了继承java.util.logging.Handler的SLF4JBridgeHandler。
适配器名称 原日框架 提供方 删除的依赖 实现方式 备注
jcl-over-slf4j apache commons-logging SLF4J API:删除commons-logging
实现:删除非SLF4J实现的实现类,如SLF4J采用Logback的实现,那么就需要删除Log4j1等实现
jcl-over-slf4j重写了commons-logging的Log和LogFactory类,做了不同的实现 JCL 是一个Log Facade,只提供 Log API,不提供实现,然后有 Adapter 来使用 Log4j 或者 JUL 作为Log Implementation,是Ceki Gulcu 认为 JCL 的 API 设计得不好,容易让使用者写出性能有问题的代码,所以重新设计了SLF4J替代JCL。
jul-to-slf4j java jdk-logging SLF4J API:删除非SLF4J之外的其他Log Facade jul-to-slf4j 下有 SLF4JBridgeHandler实现,系统启动的时候调用SLF4JBridgeHandler.removeHandlersForRootLogger();删除所有的Logger,然后调用SLF4JBridgeHandler.install();装载上SLF4J JUL是JDK自带的log功能,虽然是官方自带的log lib,但是由于性能问题和功能等问题,使用不广泛
log4j-over-slf4j apache log4j 1 SLF4J API:删除非SLF4J之外的其他Log Facade
实现:删除非SLF4J实现的实现类,如SLF4J采用Logback的实现,那么就需要删除Log4j1等实现
log4j-over-slf4j 重写了log4j 1 的Logger和LogFactory类,做了不同的实现 Log4j 在设计上非常优秀,对后续的 Java Log 框架有长久而深远的影响。Log4j 的短板在于性能,在Logback 和 Log4j2 出来之后,Log4j的使用也减少了
log4j-to-slf4j apache Log4j 2 Log4j 2 API:删除非SLF4J之外的其他Log Facade
实现:删除非SLF4J实现的实现类,如SLF4J采用Logback的实现,那么就需要删除Log4j2等实现
log4j-to-slf4j 使用OSGI SPI的形式为org.apache.logging.log4j.spi.Provider提供了SLF4J的实现 Log4j 2的性能很好,是未来之星!官方文档

2. SLF4J对接不同的日志框架实现(SLF4J—->日志框架)

官方文档

SLF4J适配不同的日志实现,是通过不同的适配器实现的。

  • 在1.8.0-alpha0以前版本采用实现org.slf4j.impl.StaticLoggerBinder的方式实现,
  • 在1.8.0-alpha0之后的版本采用提供org.slf4j.spi.SLF4JServiceProvider的SPI实现的方式实现。

显然,第一中方式不够优雅,所以Ceki Gulcu在2017年3月21日对SFL4J的提交过程当中删除org.slf4j.impl.StaticLoggerBinder,增加了org.slf4j.spi.SLF4JServiceProvider,将原来的查找实现的方式变成了查找SPI服务的方式,但是最新的SPI方案并没有做对久的org.slf4j.impl.StaticLoggerBinder方式的兼容,这个动作欠妥的,比如SLF4J与Logback的配合上就有问题,类似的问题会出现在其他日志实现当中。

SLF4J 1.8.0以前版本 SLF4J 1.8.0以后版本
Logback 1.3.0以前版本 正常使用
Logback 1.3.0以后版本 无法正常使用

log4j-slf4j-impl是的Log4j 2提供的对SLF4J的实现,由于是第三方提供的方案,所以其采用了实现org.slf4j.impl.StaticLoggerBinder的方案进行扩展。

2.1 适配器名称说明

适配器名称 目标实现 提供方 备注
slf4j-jdk14 jdk-logging J.U.L SLF4J
logback-classic Logback Logback Logback与SLF4J都是Ceki Gulcu的作品,Logback默认带SLF4J的适配
slf4j-jcl apache commons-logging SLF4J
slf4j-log4j12 Log4j 1 SLF4J
log4j-slf4j-impl Log4j 2 Log4j 2 官方文档

3. 图例

参考:Java 日志框架解析(上) - 历史演进
SLF4J与Logback、Log4j1、Log4j2、JCL、J.U.L是如何关联使用的_第1张图片

你可能感兴趣的:(Java,EE)