Spring Boot 3升级遇LoggerFactory冲突问题求助
问题背景
我们正将应用升级至Spring Boot 3,运行时出现LoggerFactory冲突问题。通过Slf4j使用Logback作为日志实现,引入了spring-boot-starter-logging模块,未在build.gradle中指定Slf4j或Logback的版本。
依赖详情
集成测试运行时类路径的日志相关依赖如下:
integrationTestRuntimeClasspath - Runtime classpath of source set 'integration test'. +--- net.logstash.logback:logstash-logback-encoder:6.6 | \--- com.fasterxml.jackson.core:jackson-databind:2.12.0 -> 2.14.2 | +--- com.fasterxml.jackson.core:jackson-annotations:2.14.2 | | \--- com.fasterxml.jackson:jackson-bom:2.14.2 | | +--- com.fasterxml.jackson.core:jackson-annotations:2.14.2 (c) | | +--- com.fasterxml.jackson.core:jackson-core:2.14.2 (c) | | +--- com.fasterxml.jackson.core:jackson-databind:2.14.2 (c) | | +--- com.fasterxml.jackson.datatype:jackson-datatype-guava:2.14.2 (c) | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.2 (c) | | +--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.2 (c) | | +--- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.14.2 (c) | | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2 (c) | | \--- com.fasterxml.jackson.datatype:jackson-datatype-joda:2.14.2 (c) | +--- com.fasterxml.jackson.core:jackson-core:2.14.2 | | \--- com.fasterxml.jackson:jackson-bom:2.14.2 (*) | \--- com.fasterxml.jackson:jackson-bom:2.14.2 (*) +--- org.springframework.boot:spring-boot-starter-logging -> 3.0.5 | \--- ch.qos.logback:logback-classic:1.4.6 | +--- ch.qos.logback:logback-core:1.4.6 | \--- org.slf4j:slf4j-api:2.0.4 -> 2.0.7 +--- org.springframework:spring-context -> 6.0.7 | +--- org.springframework:spring-aop:6.0.7 | | +--- org.springframework:spring-beans:6.0.7 | | | \--- org.springframework:spring-core:6.0.7 | | | \--- org.springframework:spring-jcl:6.0.7 | | \--- org.springframework:spring-core:6.0.7 (*) | +--- org.springframework:spring-beans:6.0.7 (*) | +--- org.springframework:spring-core:6.0.7 (*) | \--- org.springframework:spring-expression:6.0.7 | \--- org.springframework:spring-core:6.0.7 (*) +--- org.springframework:spring-beans -> 6.0.7 (*) +--- com.fasterxml.jackson.core:jackson-databind:{strictly 2.14.2} -> 2.14.2 (*) +--- com.fasterxml.jackson.core:jackson-annotations:{strictly 2.14.2} -> 2.14.2 (*) +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.69 | \--- org.apache.tomcat:tomcat-annotations-api:9.0.69 -> 10.1.7 +--- commons-logging:commons-logging:1.1.3 -> 1.2
现有配置
多模块构建的所有模块中应用了以下排除规则和依赖:
configurations.all { // Short version cache so we don't accidentally use old versions resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes' exclude group: 'org.apache.logging.log4j', module: 'log4j-to-slf4j' exclude group: 'org.apache.logging.log4j', module: 'log4j-api' exclude group: 'org.slf4j', module: 'jul-to-slf4j' exclude group: 'org.slf4j', module: 'slf4j-log4j' exclude group: 'org.slf4j', module: 'slf4j-log4j12' } dependencies { implementation 'net.logstash.logback:logstash-logback-encoder:6.6' implementation 'org.springframework.boot:spring-boot-starter-logging'
错误信息
运行集成测试时出现如下错误:
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.helpers.SubstituteLoggerFactory loaded from file: .../.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.7/41eb7184ea9d556f23e18b5cb99cad1f8581fc00/slf4j-api-2.0.7.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.helpers.SubstituteLoggerFactory
奇怪的是,只有部分集成测试受影响,其余测试运行正常。
编辑:调试发现org.slf4j.LoggerFactory初始化时返回的是SubstituteLogger。
解决方案建议
1. 检查类路径加载顺序
部分测试失败说明类加载顺序存在差异,SubstituteLoggerFactory被优先加载。可以通过以下方式排查:
- 为失败的测试添加JVM参数
-verbose:class,查看日志类的加载顺序,确认是否有其他类库提前触发了SLF4J初始化。 - 检查测试类的依赖,是否某个测试引入了特殊依赖,导致SLF4J在Logback之前被初始化。
2. 强制SLF4J与Logback版本对齐
Spring Boot 3.0.5依赖的SLF4J版本是2.0.4,当前被升级到了2.0.7,虽版本兼容,但可强制锁定版本避免潜在问题:
configurations.all { resolutionStrategy.force 'org.slf4j:slf4j-api:2.0.4' resolutionStrategy.force 'ch.qos.logback:logback-classic:1.4.6' resolutionStrategy.force 'ch.qos.logback:logback-core:1.4.6' }
3. 排查测试初始化逻辑
部分测试可能在Spring Boot上下文初始化前就尝试获取Logger,此时Logback还未加载,SLF4J会用SubstituteLoggerFactory作为占位符。可以:
- 检查测试类是否使用了
@BeforeClass等提前执行的代码,其中包含日志操作。 - 确保所有测试都通过Spring Boot的
@SpringBootTest或相关注解初始化上下文,保证Logback先完成加载。
4. 移除commons-logging依赖
Spring的spring-jcl模块已替代commons-logging,但当前依赖中仍有commons-logging:1.2,可排除该依赖避免冲突:
configurations.all { exclude group: 'commons-logging', module: 'commons-logging' }
5. 升级logstash-logback-encoder版本
当前使用的logstash-logback-encoder 6.6版本需确认与Logback 1.4.6(Spring Boot 3.0.5依赖)的兼容性,可升级到适配版本(如7.4及以上):
implementation 'net.logstash.logback:logstash-logback-encoder:7.4'
内容的提问来源于stack exchange,提问作者Ben Green

