JDK版本:jdk17
IDEA版本:IntelliJ IDEA 2022.1.3
SpringBoot 版本:v2.5.7
maven版本:3.6.3
问题描述:
当SpringBoot项目中引入多个依赖,如果多个依赖中都引入了SLF4J类库,启动项目时就会报以下错误
如下图所示
完整报错信息如下
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/ins/apache-maven-3.6.3/localReposity/ch/qos/logback/logback-classic/1.2.7/logback-classic-1.2.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/ins/apache-maven-3.6.3/localReposity/org/slf4j/slf4j-simple/1.7.32/slf4j-simple-1.7.32.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
原因分析:
当前项目的依赖中类路径中存在多个绑定的SLF4J类库,产生冲突了
那为什么SpringBoot项目不允许存在多个绑定SLF4J类库的依赖?
Spring Boot项目中不建议存在多个SLF4J绑定类库的依赖。虽然在技术上,一个项目可以包含多个SLF4J绑定(即实现了SLF4J API的具体日志实现库,如Logback、Log4j、SLF4J Simple等),但这样做会导致以下问题:
-
冲突与不确定性
:当类路径中存在多个SLF4J绑定时,SLF4J会在启动时警告存在多个绑定,并会选择其中一个绑定进行初始化。这种选择通常是不确定的,取决于类加载器的加载顺序。由于不同的日志实现可能存在差异,使用非预期的日志系统可能会导致日志输出不符合预期,甚至丢失日志信息。
-
资源浪费
:多个绑定意味着类路径中加载了多个日志实现库,这不仅增加了应用程序的内存占用,还可能导致CPU资源浪费,因为未被选中的日志库仍会被加载但并未实际使用。
-
配置复杂性
:如果项目中同时存在多个日志实现,配置管理会变得复杂。您可能需要为每个日志实现分别配置,而这可能导致配置冲突或难以预期的行为。此外,当需要切换日志实现时,需要更新多个配置文件,增加了维护负担。
-
潜在的兼容性问题
:不同的日志实现可能存在细微的API差异或行为差异。同时使用多个绑定可能导致某些特性无法正常工作,或者在特定场景下产生难以诊断的问题。
所以,为了避免上述问题,Spring Boot项目通常遵循以下原则:
-
明确指定一个日志实现:在项目中只保留一个SLF4J绑定,通常是Logback,因为它与Spring Boot有着良好的集成,且默认由Spring Boot Starter Logging提供。如果您有特定需求需要使用其他日志实现(如Log4j2),则应确保排除其他所有SLF4J绑定。
-
清理类路径:
定期检查依赖管理工具(如Maven或Gradle)生成的依赖报告,确保没有意外引入的SLF4J绑定。如果有,通过排除依赖或调整依赖版本来移除多余的绑定。 -
遵循最佳实践:
遵循Spring Boot官方文档推荐的日志配置方法,确保所有日志配置集中且一致。避免在应用代码中硬编码日志实现相关的配置或API调用。
因此,尽管Spring Boot项目在技术上可以包含多个SLF4J绑定类库,但从最佳实践和避免潜在问题的角度出发,应当确保项目中只有一个选定的日志实现库与SLF4J绑定。
解决方案:
- 寻找项目中到底是哪些依赖都绑定了SLF4J类库
在IDEA底下
终端
中使用mvn dependency:tree
命令列出当前项目所引入的依赖
注意
上述mvn命令的前提是你的电脑配了mvn系统环境变量
如果想要更详细的探究依赖引入情况,可以参考如下步骤
①将鼠标光标置于当前项目的pop.xml文件中,右击按照以下步骤打开项目依赖图
②Ctrl + F 打开图元素选框,选择包含SLF4J的图元素,它会自动定位于所选定的图元素
注意
你可以根据带箭头的直线前后详细低地查看各个类库的依赖引入关系
- 通过上述命令得知,spring-boot-starter-test类库与dashscope-sdk-java类库都绑定了SLF4J类库,任选其一,在pop.xml中移除所绑定的SLF4J类库即可(我这里是在dashscope-sdk-java里移除了SLF4J的绑定)
代码示例如下
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>2.10.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
刷新Maven变更
4. 重启项目,SLF4J报错信息消失
至此,debug解决问题成功!!!