Spring boot 3 日志依赖冲突

问题描述 投票:0回答:2

目前我们的应用程序正在升级到 Spring Boot 3,我们在运行时遇到了一些记录器工厂冲突的问题。

我们使用 logback 来实现日志记录,但通过 slf4j。

我们引入了

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

奇怪的是,这仅影响部分集成测试。其他都按预期运行。

我在这里有点不知所措。我不能排除 logback 或 slf4j,因为它们都是必需的。任何帮助将不胜感激。

编辑我今天早上做了一些调试,似乎正在发生的事情是,当

org.slf4j.LoggerFactory
正在初始化时,它返回替代记录器。

spring-boot gradle logback slf4j
2个回答
1
投票

我们的问题已经到了底部。以下是所发生事情的摘要:

  • LoggerFactory
    中,我们可以看到SLF4J正在寻找Logback作为提供者,并开始初始化它。
  • 在某些情况下,初始化需要一秒钟的时间。
  • 初始化花了一段时间的原因是因为它正在使用我们的主应用程序
    logback.xml
    并且显然初始化
    logstash
    附加程序是一个相当慢的过程。

问题的根本原因似乎是在 slf4j 初始化时,对

LoggerFactory#getProvider
方法的任何请求都会返回替代提供者,此时 Spring Boot 中的
LogbackLoggingSystem#getLoggerContext
会抛出异常,因为返回的
LoggerFactory
是无效。

我将针对 slf4j 的这种行为提出一个错误。我觉得如果它正在初始化,它不应该只返回一个虚拟实现。


0
投票

Ben,您最终是否在 SLF4J 上产生了问题?我刚刚将我的项目更新到 Spring Boot 3.2.2(从 2.7.x)并遇到了同样的问题。我的具体错误是“LoggerFactory不是Logback LoggerContext,但Logback位于类路径上。删除Logback或竞争实现(从文件加载类org.slf4j.helpers.NOPLoggerFactory:/.m2/org/slf4j/slf4j-api/ 2.0.11/slf4j-api-2.0.11.jar)。如果您使用 WebLogic,则需要将“org.slf4j”添加到 WEB-INF/weblogic.xml 中的首选应用程序包中:org.slf4j.helpers .NOPLoggerFactory”

我们使用的是 spring-boot-starter-logging 标准的 logback,而不是使用 Log4j。我们也仅使用文件和控制台附加程序,因此初始化不会像您的情况那样花费很长时间。知道这是怎么回事吗?

© www.soinside.com 2019 - 2024. All rights reserved.