问题本质是反向桥接导致的循环委托,如log4j-over-slf4j与slf4j-log4j12共存引发Log4j↔SLF4J闭环,造成类加载失败或StackOverflowError;需通过dependency:tree检查并确保桥接单向、不共存,Spring Boot推荐零桥接方案。

这个问题本质是桥接器(bridging)用错了方向,不是“多个”,而是“反向桥接”引发的循环委托——比如 log4j-over-slf4j 把 Log4j1.x 的日志调用转给 SLF4J,但同时项目又引入了 slf4j-log4j12(把 SLF4J 调用再转回 Log4j1.x),形成闭环:Log4j → SLF4J → Log4j → SLF4J… 启动时就会卡在类加载或抛出 NoClassDefFoundError、StackOverflowError 甚至 ClassCastException(如 SLF4JLoggerContext 强转失败)。
确认是否真有桥接环路
看错误日志里的绑定路径和异常栈:
- 如果出现类似
org.apache.log4j.Level找不到,但你没写 Log4j1.x 的代码 → 很可能是log4j-over-slf4j在运行时试图调用 Log4j1.x 类,而你只排除了slf4j-log4j12却没配 Log4j1.x 实现; - 如果报
SLF4JLoggerContext cannot be cast to Log4j2LoggingSystem.getLoggerContext→ 是log4j-slf4j-impl(Log4j2 的 SLF4J 绑定)和log4j-to-slf4j(Log4j2 桥接到 SLF4J)被同时引入; - 运行
mvn dependency:tree -Dincludes=org.slf4j:*,org.apache.logging.log4j:*,重点检查是否同时存在:
log4j-over-slf4j + slf4j-log4j12,或
log4j-to-slf4j + log4j-slf4j-impl。
桥接包必须单向使用,不能共存
桥接器只应在“旧日志 API 迁移过渡期”使用,且严格遵循方向性:
-
log4j-over-slf4j:替代原有log4j-1.2.x.jar,让老项目里import org.apache.log4j.*的代码走 SLF4J → 你必须彻底移除 log4j-1.2.x 和 slf4j-log4j12; -
log4j-to-slf4j:替代log4j-api-2.x+log4j-core-2.x,把 Log4j2 的日志调用转给 SLF4J → 你必须不引入任何 SLF4J 绑定(如 logback-classic、log4j-slf4j-impl); -
jcl-over-slf4j/jul-to-slf4j同理:只桥接,不回流。
Spring Boot 项目推荐零桥接方案
Spring Boot 2.0+ 默认用 Logback,无需桥接。若你明确要 Log4j2:
立即学习“Java免费学习笔记(深入)”;
- 先排除 Spring Boot 默认的 Logback:
<exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></exclusion>; - 再显式引入 Log4j2 starter:
<artifactId>spring-boot-starter-log4j2</artifactId>; - 确保 不额外引入:
log4j-to-slf4j、log4j-over-slf4j、slf4j-log4j12、slf4j-simple等任意其他绑定或桥接器。
已污染项目快速清理法
如果已经混入多个桥接包,不要逐个排除,直接清空再重建:
- 执行
mvn clean dependency:purge-local-repository清掉本地缓存; - 在 IDE 中关闭自动导入,手动删掉
lib/或target/lib/下所有含log4j-over-、log4j-to-、slf4j-jdk14、slf4j-simple的 JAR; - 只保留且仅保留一个 SLF4J binding:
– Logback:logback-classic
– Log4j2:log4j-slf4j-impl
– JUL:slf4j-jdk14(慎用,功能弱); - 重启应用,验证
SLF4J: Actual binding is of type [...]输出唯一且符合预期。


















