问题
今天忽然发现轻境界无法输出日志了,控制台输出以下警告⚠️:
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8.
SLF4J: Ignoring binding found at [jar:file:/Users/dhu/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.1.11/ccedfbacef4a6515d2983e3f89ed753d5d4fb665/logback-classic-1.1.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.
看来是SLF4J的依赖出问题了。问题是我没修改任何依赖啊!什么都没改,也会出问题?
探索
先排查吧。点击SLF4J的官网链接,据文档所述,这是因为slf4j-api 1.8不兼容旧版logback-classic库。
小知识:SLF4J是一个日志接口库,Logback是一个日志实现库,logback-classic能桥接SLF4J和Logback。小知识:传递性依赖是指项目所直接依赖的库又间接依赖了更多的库,例如Spring依赖CGLib。
IDE中的Gradle依赖树显示我依赖了slf4j-api 1.8-alpha0和logback-classic 1.1.11。但是我明确记得没依赖过alpha版本的slf4j-api,而这个版本需要Logback 1.2.x才能支持!现在引用的Logback 1.1.11是不行的!
在项目中只有Spring Boot和Ebean ORM依赖于SLF4J,因为上周升级了Spring Boot,所以我先怀疑Spring Boot——我尝试排除它对slf4j-api和logback-classic的传递性依赖,对build.gradle修改代码如下:
compile ("org.springframework.boot:spring-boot-starter-aop:${springBootVersion}") {
exclude group: 'org.slf4j', module: 'slf4j-api'
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
然并卵,控制台仍然输出警告。
解决
我使用Gradle的依赖分析功能,输入命令./gradlew dependencyInsight --dependency slf4j-api
,输出如下:
注意看最后一段:org.slf4j:slf4j-api:[1.7.12,) -> 1.8.0-alpha0
,这是罪魁祸首!它是被avaje-ebeanorm
间接引用进来的,是一个传递性依赖!
它的依赖区间是[1.7.12,)
,没有上限,意思是凡是1.7.12版本以上的都可以,这就导致——当slf4j-api发布了1.8.0-alpha0之后,如果Gradle恰好联网查了一下,就会使用最新版的1.8.0-alpha0!
在一个项目中,如果同时存在高版本依赖和低版本依赖,高版本就会覆盖低版本。虽然其他的依赖项指定了依赖区间的上限,但是只要有一个奇怪的依赖混进来引用了更高版本的库,就会覆盖其他所有的低版本。
于是我排除avaje-ebeanorm
引入的间接依赖,修改build.gradle如下:
compile ('org.avaje.ebeanorm:avaje-ebeanorm:7.9.1') {
exclude group: 'org.slf4j', module: 'slf4j-api'
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
再次运行依赖分析命令./gradlew dependencyInsight --dependency slf4j-api
,输出如下:
正常了!
以后再遇这种问题,第一时间用Gradle的dependencyInsight功能,棒!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。