文章目录
SLF4J 2.X 版本升级相关问题
之前整理的Java Log体系中的使用SLF4J
版本都是1.7.36
,对于高于这个1.7
版本的SLF4J 的日志实现做绑定时,会出现无法绑定的提示
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J(W): Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.
SLF4J(W): Ignoring binding found at [jar:file:/D:/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.23.1/log4j-slf4j-impl-2.23.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J(W): See https://www.slf4j.org/codes.html#ignoredBindings for an explanation.
这些警告信息输出来源为
org.slf4j.LoggerFactory
这个类
这个是因为SLF4J 2.X
版本开始后使用了新的ServiceLoader
机制加载,但老的一些绑定的包是不支持这个机制的,因此需要使用新的包来解决这些问题。
Java Log SLF4j2.x Log4j2 binding demo
测试Slf4j2.x binding (桥接到 Log4j2
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用Log4j2
输出日志
要实现这个效果就必须引入对应日志框架的SLF4J
的Over包,将日志重定向到SLF4J
。但由于SLF4J
并没有一个具体的日志实现,所以还得找一个具体的日志实现,这个demo选择的是Log4j2
作为最终的日志实现。
相关版本号
<properties>
<java.version>21</java.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.3.1</spring-boot.version>
<slf4j.version>2.0.13</slf4j.version>
<log4j2.version>2.23.1</log4j2.version>
</properties>
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
Logback
本身就支持并使用了SLF4J
门面 ,没有要Over
也不需要Over
,因此不参与本测试。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
然后引入jcl-over-slf4j
包就可以,当然也可以用spring-jcl
,效果一样。
Log4j
Over 处理
Log4j
除了需要引入log4j-over-slf4j
包外,还要排除掉log4j
本身的依赖包,否则Over是无效的。
<!--引入Log4j-->
<!-- <dependency>-->
<!-- <groupId>log4j</groupId>-->
<!-- <artifactId>log4j</artifactId>-->
<!-- <version>1.2.17</version>-->
<!-- </dependency>-->
Log4j2
Over 处理
本Demo是最终是使用log4j2
输出,因此不能再把Log4j2
Over掉了,因此不做Over处理。
<!-- LOG4J2 over SLF4j -->
<!--<dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-to-slf4j</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!--</dependency>-->
Jul
Over 处理
本次使用的是Spring Boot 3.3.1
版本,在Spring Boot 3.0版本开始就已经移除了SLF4j对于JUL的Over的处理,因此在Spring Boot 3.0 版本后,不能再直接把JUL Over到SLF4J,只能根据最终的日志实现来将JUL OVER到对应的日志实现
具体情况就不在这里解释,会另开一篇来说明这个问题。这里就简单做了一个解决方案,就是把JUL Over到LOG4J2。
添加jul over log4j2
包
<!-- 添加jul over log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>${log4j2.version}</version>
</dependency>
移除jul over slf4j
包
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
SLF4J2.x
Binding Log4j2
的处理
引入SLF4J2.x
的Log4j2
实现包log4j-slf4j2-impl
, 对于SLF4J
来说,自2.0 版本开始使用ServiceLoader
机制加载,因此不能在继续使用1.0 版本的log4j-slf4j-impl
包.
<!-- 添加Log4j2 binding slf4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出,JCL
在有Log4j
的时候,使用的就是Log4j
实现。
2024-07-12 15:20:51 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2024-07-12 15:20:51 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2024-07-12 15:20:51 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2024-07-12 15:20:51 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2024-07-12 15:20:51 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
7月 12, 2024 3:20:51 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
7月 12, 2024 3:20:51 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2024-07-12 15:20:51 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2024-07-12 15:20:51 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2024-07-12 15:20:51 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2024-07-12 15:20:51 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2024-07-12 15:20:51 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
[2024-07-12 15:20:51.241] [] [main] INFO : [c.f.LogLog4j2Tests:19] - LogLog4j2Tests 这是info日志...
[2024-07-12 15:20:51.244] [] [main] WARN : [c.f.LogLog4j2Tests:20] - LogLog4j2Tests 这是warn日志...
[2024-07-12 15:20:51.245] [] [main] ERROR: [c.f.LogLog4j2Tests:21] - LogLog4j2Tests 这是error日志...
[2024-07-12 15:20:51.248] [] [main] INFO : [c.f.LogLog4j2Tests:22] - LogLog4j2Tests 这是info日志...test
[2024-07-12 15:20:51.249] [] [main] INFO : [c.f.LogLog4j2Tests:23] - public class org.apache.logging.slf4j.Log4jLogger
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
[2024-07-12 15:00:36.469] [] [main] INFO : [c.f.LogJclTests:23] - LogJclTests 这是info日志...
[2024-07-12 15:00:36.469] [] [main] WARN : [c.f.LogJclTests:24] - LogJclTests 这是warn日志...
[2024-07-12 15:00:36.469] [] [main] ERROR: [c.f.LogJclTests:25] - LogJclTests 这是error日志...
[2024-07-12 15:00:36.469] [] [main] INFO : [c.f.LogJclTests:26] - LogJclTests public class org.apache.commons.logging.impl.SLF4JLocationAwareLog
[2024-07-12 15:00:36.474] [] [main] INFO : [c.f.LogJulTests:19] - LogJulTests 这是info日志...
[2024-07-12 15:00:36.475] [] [main] INFO : [c.f.LogJulTests:20] - LogJulTests public class java.util.logging.Logger
[2024-07-12 15:00:36.478] [] [main] INFO : [c.f.LogLog4jTests:23] - LogLog4jTests 这是info日志...
[2024-07-12 15:00:36.478] [] [main] WARN : [c.f.LogLog4jTests:24] - LogLog4jTests 这是warn日志...
[2024-07-12 15:00:36.478] [] [main] ERROR: [c.f.LogLog4jTests:25] - LogLog4jTests 这是error日志...
[2024-07-12 15:00:36.478] [] [main] INFO : [c.f.LogLog4jTests:26] - LogLog4jTests public class org.apache.log4j.Logger
[2024-07-12 15:00:36.479] [] [main] INFO : [c.f.LogLog4j2Tests:19] - LogLog4j2Tests 这是info日志...
[2024-07-12 15:00:36.479] [] [main] WARN : [c.f.LogLog4j2Tests:20] - LogLog4j2Tests 这是warn日志...
[2024-07-12 15:00:36.479] [] [main] ERROR: [c.f.LogLog4j2Tests:21] - LogLog4j2Tests 这是error日志...
[2024-07-12 15:00:36.482] [] [main] INFO : [c.f.LogLog4j2Tests:22] - LogLog4j2Tests 这是info日志...test
[2024-07-12 15:00:36.482] [] [main] INFO : [c.f.LogLog4j2Tests:23] - public class org.apache.logging.slf4j.Log4jLogger
相关资料
Demo 项目源码: java-log
参考资料:
SLF4J ignoredBindings: https://www.slf4j.org/codes.html#ignoredBindings
SLF4J 2 绑定 log4j2 : https://logging.apache.org/log4j/2.x/log4j-slf4j-impl.html
JUL 路由到 log4j2 : https://logging.apache.org/log4j/2.x/log4j-jul.html