Spring Boot 2.7.x 默认使用 logback 1.2.x 及以下版本,若升级至 1.3.x 及以上版本启动会报错。主要原因是 Spring Boot 2.7.x 依赖 logback-classic 1.2.x 中的类 org.slf4j.impl.StaticLoggerBinder,而 logback-classic 1.3.x 已删除此类。
报错原因分析
通过源码分析查找报错原因,组件版本如下:
- spring-boot: 2.7.18
- logback-classic: 1.2.11
Spring Boot 启动时会调用方法 LoggingApplicationListener.onApplicationEnvironmentPreparedEvent,其中会获取到 LoggingSystem 的实例:

生成 LoggingSystem 实例的方法是 LoggingSystem.get:

其中 SYSTEM_PROPERTY=org.springframework.boot.logging.LoggingSystem。
若 SYSTEM_PROPERTY 的值是 LoggingSystem 的实现类的类名(如 org.springframework.boot.logging.logback.LogbackLoggingSystem),则会创建这个类的实例;若值为 NONE,则生成 NoOpLoggingSystem;否则,Spring Boot 会在类路径中查找日志组件并实例化。
在 onApplicationEnvironmentPreparedEvent 中获取到 LoggingSystem 实例后,会调用 initialize 方法:

在其中会调用 initializeSystem 方法:

其中 CONFIG_PROPERTY=logging.config,即从环境变量 logging.config 中获取 logback 的配置文件,然后使用 LogbackLoggingSystem.initialize 对 logback 进行初始化:

查看 getLoggerContext() 的源代码:

可以看到 StaticLoggerBinder 是在这个地方被用到了。
解决方案
通过分析上面的源代码可知,如果想让 Spring Boot 2.7.x 使用 logback-classic 1.3.x 及以上版本,则需要先将环境变量 org.springframework.boot.logging.LoggingSystem 的值设置成 none,也就是不让 Spring Boot 帮忙初始化 logback,改由应用自己初始化 logback。
另外,logback-classic 升级至 1.3.x 以上版本,slf4j 也要升级至 1.8.x 及以上版本。
最后,如果 logback 配置文件的路径以前是通过环境变量 logging.config 配置的,则需要将 logback 配置文件的路径通过环境变量 logback.configurationFile 进行配置:

其中 CONFIG_FILE_PROPERTY=logback.configurationFile。
上述源代码属于 logback-classic 组件,版本如下:
- logback-classic: 1.3.15
该解决方案可在 logback 官方网站下载页面查阅:
https://logback.qos.ch/download.html
进一步说明
如果应用是在 servlet 3.0 以上容器部署时,logback 会由 ch.qos.logback.servlet.LogbackServletContainerInitializer 初始化,而 Spring Boot 由 org.springframework.web.SpringServletContainerInitializer 初始化,这 2 个类都实现了 javax.servlet.ServletContainerInitializer 接口。一般 servlet 容器会先执行 LogbackServletContainerInitializer,这样就会把 logback 初始化完成,所以 logback 一般不是在执行 SpringServletContainerInitializer 的过程中初始化的。

