Как подавить SLF4J Предупреждение о множественных привязках?

Мой проект Java имеет зависимости с различными версиями SLF4J. Как я могу подавить раздражающие предупреждения?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:xyz234/lib/slf4j-
log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in [jar:file:xyz123/.m2/repository/org/slf4j/slf4j-log4j12
/1.6.0/slf4j-log4j12-1.6.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

PS: Это не тот же вопрос, что и предупреждение slf4j о том, что одна и та же привязка является дубликатом, ответ на этот вопрос заключается в том, как избавиться от предупреждения о ложной тревоге, но в моем случае это истинное предупреждение. PSS: Извините, я забыл упомянуть: я использую Maven, и SLF4J входит в зависимости моих зависимостей.

5 ответов

Решение

Удалить один из slf4j-log4j12-1.5.8.jar или же slf4j-log4j12-1.6.0.jar из класса. Ваш проект не должен зависеть от разных версий SLF4J. Я предлагаю вам использовать только 1.6.0.

Если вы используете Maven, вы можете исключить транзитивные зависимости. Вот пример:

<dependency>
    <groupId>com.sun.xml.stream</groupId>
    <artifactId>sjsxp</artifactId>
    <version>1.0.1</version>
    <exclusions>
        <exclusion>
            <groupId>javax.xml.stream</groupId>
            <artifactId>stax-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

В текущей реализации slf4j-api невозможно удалить эти предупреждения. org.slf4j.LoggerFactory класс печатает сообщения:

  ...
  if (implementationSet.size() > 1) {
    Util.report("Class path contains multiple SLF4J bindings.");
    Iterator iterator = implementationSet.iterator();
    while(iterator.hasNext()) {
      URL path = (URL) iterator.next();
      Util.report("Found binding in [" + path + "]");
    }
    Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
  }
  ...

Util класс следующий:

public class Util {

  static final public void report(String msg, Throwable t) {
    System.err.println(msg);
    System.err.println("Reported exception:");
    t.printStackTrace();
  }
  ...

report метод пишет прямо в System.err, Обходной путь мог бы заменить System.err с System.setErr() до первого LoggerFactory.getLogger() позвоните, но вы можете потерять другие важные сообщения, если вы сделаете это.

Конечно, вы можете скачать исходный код и удалить эти Util.report звоните и используйте ваш модифицированный slf4j-api в вашем проекте.

    PrintStream filterOut = new PrintStream(System.err) {
        public void println(String l) {
            if (! l.startsWith("SLF4J")) {
                super.println(l);
            }
        }
    };
    System.setErr(filterOut);

и вуаля!

Вы прочитали URL, на который ссылается предупреждение?

SLF4J: See [http://www.slf4j.org/codes.html#multiple_bindings][1] for an explanation.

Вот что говорит ссылка:

SLF4J API предназначен для привязки к одной и только одной базовой структуре ведения журнала одновременно. Если в пути к классу присутствует более одной привязки, SLF4J выдаст предупреждение с указанием расположения этих привязок. Когда это произойдет, выберите одну и только одну привязку, которую вы хотите использовать, и удалите другие привязки.

Например, если у вас есть и slf4j-simple-1.6.2.jar, и slf4j-nop-1.6.2.jar на пути к классам, и вы хотите использовать привязку nop (без операции), тогда удалите slf4j-simple- 1.6.2.jar из класса путь.

Обратите внимание, что предупреждение, генерируемое SLF4J, является предупреждением. SLF4J будет по-прежнему связываться с первым фреймворком, найденным в пути к классам.

При использовании maven всегда используйте команду

mvn dependency:tree

Это перечислит все зависимости, добавленные в проект, включая зависимости от jar, которые мы включили. Здесь мы можем указать несколько версий или несколько копий банок с другими банками, которые были добавлены. использование

<exclusions><exclusion><groupId></groupId><artifactId></artifactId></exclusion></exclusions>

в <dependency> элемент для исключения тех, которые конфликтуют. Всегда повторяйте команду maven выше после каждого исключения, если проблема не устранена.

Иногда исключение 2-го регистратора из пути к классам потребует слишком много искажений, и предупреждение невероятно раздражает. Маскировка стандартной ошибки, как кажется, работает в самом начале программы, например

    public static void main(String[] args)
    {
        org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF);
        PrintStream old = System.err;
        System.setErr(new PrintStream(new ByteArrayOutputStream()));
        // ... trigger it ...
        System.setErr(old);

        ...

посредством чего trigger it part должен вызвать некоторую функцию nop, которая обращается к системе регистрации и в противном случае вызвала бы генерацию сообщения.

Я не рекомендовал бы это для производственного кода, но для целей skunkworks это должно помочь.

Если вы используете старую версию Jetty (скажем, Jetty 6), вам может потребоваться изменить порядок загрузки классов для веб-приложения, чтобы сделать его более приоритетным, чем контейнер. Вы можете сделать это, добавив эту строку в xml-файл контейнера:

<Set name="parentLoaderPriority">false</Set>
Другие вопросы по тегам