原文链接:https://blog.csdn.net/yangzl2008/article/details/81503579

当项目是使用多种日志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。

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。

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的方案进行扩展。

适配器名称说明

适配器名称 目标实现 提供方 备注
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 官方文档