1. Overview
1.概述
When we use SLF4J in our applications, we sometimes see a warning message about multiple bindings in the classpath printed to the console.
当我们在应用程序中使用SLF4J时,我们有时会看到一个关于classpath中多个绑定的警告信息打印到控制台。
In this tutorial, we’ll try to understand why we see this message and how to resolve it.
在本教程中,我们将尝试了解为什么我们会看到这个消息,以及如何解决它。
2. Understanding the Warning
2.了解警告
First, let’s look at a sample warning:
首先,让我们看看一个警告样本。
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:.../slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:.../logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
This warning is telling us that SLF4J has found two bindings. One is in slf4j-log4j12-1.7.21.jar, and the other is in logback-classic-1.1.7.jar.
这个警告是告诉我们,SLF4J找到了两个绑定。一个是在slf4j-log4j12-1.7.21.jar,另一个是在logback-classic-1.1.7.jar。
Now let’s understand why we see this warning.
现在我们来了解一下为什么我们会看到这个警告。
The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks. It allows us to plug in our desired logging framework at deployment time.
Simple Logging Facade for Java (SLF4J)作为各种日志框架的简单接口或抽象。它允许我们在部署时插入我们想要的日志框架。
To achieve this, SLF4J looks for bindings (aka providers) on the classpath. Bindings are basically implementations of a particular SLF4J class meant to be extended to plug in a specific logging framework.
为了实现这一点,SLF4J在classpath上寻找绑定(又称提供者)。绑定基本上是一个特定的SLF4J类的实现,旨在扩展到插入一个特定的日志框架。
By design, SLF4J will only bind with one logging framework at a time. Consequently, if more than one binding is present on the classpath, it will emit a warning.
根据设计,SLF4J一次只能与一个日志框架进行绑定。因此,如果classpath上存在多个绑定,它将发出一个警告。
It is worth noting that embedded components such as libraries or frameworks should never declare a dependency on any SLF4J binding. This is because when a library declares a compile-time dependency on an SLF4J binding, it imposes that binding on the end user. Obviously, this negates SLF4J’s basic purpose. So, they should only depend on the slf4j-api library.
值得注意的是,嵌入式组件(如库或框架)不应该声明对任何SLF4J绑定的依赖性。这是因为当一个库声明了对SLF4J绑定的编译时依赖时,它将该绑定强加给了最终用户。很明显,这否定了SLF4J的基本目的。所以,他们应该只依赖slf4j-api库.。
It is also important to note that this is only a warning. If SLF4J finds multiple bindings, it will pick one logging framework from the list and bind with it. As can be seen on the last line of the warning, SLF4J has chosen Log4j by using org.slf4j.impl.Log4jLoggerFactory for the actual binding.
同样重要的是,注意这只是一个警告。如果SLF4J发现了多个绑定,它将从列表中挑选一个日志框架并与之绑定。从警告的最后一行可以看出,SLF4J通过使用org.slf4j.impl.Log4jLoggerFactory来选择Log4j进行实际绑定。
3. Finding the Conflicting JARs
3.找到冲突的JARs
The warning lists the locations of all the bindings it finds. Usually, this is sufficient information to identify the unscrupulous dependency that transitively pulls in an unwanted SLF4J binding into our project.
该警告列出了它发现的所有绑定的位置。通常情况下,这些信息足以识别出不道德的依赖关系,这些依赖关系将不需要的SLF4J绑定拉入我们的项目。
If it’s not possible to identify the dependency from the warning, we can use the dependency:tree maven goal:
如果无法从警告中确定依赖关系,我们可以使用dependency:tree maven目标。
mvn dependency:tree
This will display the dependency tree for the project:
这将显示项目的依赖树。
[INFO] +- org.docx4j:docx4j:jar:3.3.5:compile
[INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.21:compile
[INFO] | +- log4j:log4j:jar:1.2.17:compile
[INFO] +- ch.qos.logback:logback-classic:jar:1.1.7:compile
[INFO] +- ch.qos.logback:logback-core:jar:1.1.7:compile
We’re using Logback for logging in our application. So, we’ve deliberately added the Logback binding, present in the logback-classic JAR. But the docx4j dependency has also pulled in another binding with the slf4j-log4j12 JAR.
我们在应用程序中使用Logback进行日志记录。因此,我们特意添加了Logback绑定,存在于logback-classic JAR中。但是,docx4j依赖性也拉入了另一个slf4j-log4j12 JAR的绑定。
4. Resolution
4.决议
Now that we know the offending dependency, we just need to exclude the slf4j-log4j12 JAR from the docx4j dependency:
现在我们知道了违规的依赖关系,我们只需要将slf4j-log4j12 JAR从docx4j依赖关系中排除。
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>${docx4j.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Since we’re not going to use Log4j, it might be a good idea to exclude it as well.
既然我们不打算使用Log4j,把它也排除在外也许是个好主意。
5. Conclusion
5.结论
In this article, we saw how we can resolve the frequently seen warning about multiple bindings emitted by SLF4J.
在这篇文章中,我们看到如何解决经常看到的关于SLF4J发出的多个绑定的警告。
The source code that accompanies this article is available over on GitHub.
伴随着这篇文章的源代码可以在GitHub上找到。