强制slf4j使用logback

33
有没有办法强制slf4j使用指定的日志提供程序(在我的情况下是logback)?就像他们文档中所说: 当类路径上存在多个绑定时, SLF4J API旨在一次只绑定一个底层日志框架。如果类路径上存在多个绑定,则SLF4J将发出警告,列出这些绑定的位置。 当类路径上有多个绑定可用时,请选择一个并仅选择要使用的一个绑定,并删除其他绑定。例如,如果您在类路径上同时拥有slf4j-simple-1.6.6.jar和slf4j-nop-1.6.6.jar,并且您希望使用nop(>no-operation)绑定,则从类路径中删除slf4j-simple-1.6.6.jar。如果无法删除多余的绑定,则SLF4J仍将绑定到一个日志框架/实现。从版本1.6.6开始,SLF4J将命名它实际绑定的框架/实现类。 注意,SLF4J发出的警告仅仅是一个警告。 在我的情况下,我在类路径中有log4j.jar,slf4j-log4j12.jar,log4j-over-slf4j.jar和所有logback jar文件。我知道同时拥有slf4j-log4j12.jar和log4j-over-slf4j.jar是错误的,但我的项目非常大,不总是容易找到和排除maven依赖。在这种情况下,slf4j甚至没有打印任何警告,因为我们只使用logback配置。我花了一天时间才理解这个jar混乱。 我想要的就是通过JVM参数强制slf4j使用logback,以便它可以打印警告,并且我可以在将来排除jar文件。

1
在排除Maven依赖项时,并不总是简单的。可以使用“mvn dependency:tree -Dincludes='log4j'”等命令进行排除。 - Matthew Read
3个回答

36

通常你自己的代码在类路径的最前面。因此,一种方法是创建自己的org.slf4j.impl.StaticLoggerBinder类:

package org.slf4j.impl;

import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;

/**
 * Force tests to use JDK14 for logging.
 */
@SuppressWarnings("UnusedDeclaration")
public class StaticLoggerBinder implements LoggerFactoryBinder {
    private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();

    public static String REQUESTED_API_VERSION = "1.6";

    public static final StaticLoggerBinder getSingleton() {
      return SINGLETON;
    }

    private StaticLoggerBinder() {
    }

    @Override
    public ILoggerFactory getLoggerFactory() {
        return new JDK14LoggerFactory();
    }

    @Override
    public String getLoggerFactoryClassStr() {
        return "org.slf4j.impl.JDK14LoggerFactory";
    }
}

谢谢你的回答,但我已经清理了我的类路径。 - madhead
8
即便如此,这是一个很棒的回答。 - StormeHawke
如何在Logback中使用此代码?ILoggerFactory getLoggerFactory()应该返回什么,而不是新的JDK14LoggerFactory? - nagSumanth
1
如果你从 logback-classic.jar 中复制 StaticLoggerFactory 类的代码,那应该就能用了。 - Martin Charlesworth

21
除了清理类路径之外,没有办法强制SLF4J与特定的实现绑定。
2023年更新:从SLF4J版本2.0.9开始,您可以通过"slf4j.provider"系统属性明确指定提供者类。这将绕过查找提供者的服务加载器机制,可能会缩短SLF4J的初始化时间。

8
这件事情迫切需要Logback团队解决。 - Sridhar Sarnobat
1
自其创建以来,绑定机制的唯一性是slf4j-api的核心特征。 - Ceki

3

我认为如果你把logback JAR放在类路径的开头(或放在包含slf4j实现的其他JAR之前),它将被使用。

不过,如果slf4j支持一个JVM参数来指定包含实现的JAR,并且覆盖了查找类路径的操作,那就太好了,这样你就不必处理排序类路径中的JAR,以确保使用你想要的那个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接