Что надлежащий путь состоит в том, чтобы использовать Регистратор в сериализуемом классе Java?

У меня есть следующий (сфабрикованный) класс в системе, я продолжаю работать, и Findbugs генерирует предупреждение SE_BAD_FIELD, и я пытаюсь понять, почему он сказал бы что, прежде чем я зафиксирую его в способе, которым я думал, что буду. Причина я смущен, состоит в том, потому что описание, казалось бы, указало бы, что я не использовал никакие другие несериализуемые поля экземпляра в классе, но bar.model. Нечто является также не сериализуемым и используется тем же самым способом (насколько я могу сказать), но Findbugs не генерирует предупреждения для него.

import bar.model.Foo;

import java.io.File;
import java.io.Serializable;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo implements Serializable {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final File file;
    private final List originalFoos;
    private Integer count;
    private int primitive = 0;

    public Demo() {
        for (Foo foo : originalFoos) {
            this.logger.debug(...);
        }
    }

    ...

}

Мой начальный румянец в решении должен получить ссылку регистратора от права фабрики, поскольку я использую его:

public DispositionFile() {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    for (Foo foo : originalFoos) {
        this.logger.debug(...);
    }
}

Это не кажется особенно эффективным, все же.

Мысли?

16
задан Tim Visher 10 May 2010 в 21:22
поделиться

4 ответа

Во-первых, не оптимизируйте преждевременно. Может оказаться, что LoggerFactory.getLogger () работает достаточно быстро и не вносит значительных накладных расходов во время выполнения. Если сомневаетесь, опишите его.

Во-вторых, findbugs не жалуется на использование Foo , потому что у класса нет поля типа Foo , у него есть поле типа Список . Дженерики стираются во время компиляции, в классе нет фактической ссылки на Foo , что касается определения поля. Во время выполнения тот факт, что Foo не является сериализуемым, вызовет исключение, если вы попытаетесь сериализовать экземпляр класса Demo , но findbugs не могут этого знать.

Моей первой реакцией было бы сделать Logger статическим полем, а не полем экземпляра. Должен работать нормально в этой ситуации.

public class Demo implements Serializable {
   private static final Logger logger = LoggerFactory.getLogger(Demo.class);

   // .. other stuff
}
19
ответ дан 30 November 2019 в 16:57
поделиться

Я не хочу, чтобы что-то взлетело по касательной, но рассматривали ли вы обычную инициализацию логгеров?

private static final Logger logger = LoggerFactory.getLogger(Demo.class);

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

Между прочим, автор SL4J сказал (в критике оболочек Log4J, таких как общее ведение журнала),

Чаще всего эти обертки {{1 }} имеют сомнительное качество, так что стоимость неактивных (или отключенных) операторов ведения журнала умножается на коэффициент 1'000 (одна тысяча) по сравнению с {{ 1}} прямое использование log4j. Самая распространенная ошибка в классах-оболочках - это вызов метода Logger.getLogger при каждом запросе журнала. Это гарантированно нанесет ущерб производительности вашего приложения. Действительно!!!

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

7
ответ дан 30 November 2019 в 16:57
поделиться

FindBugs вводит вас в заблуждение в данном конкретном случае, потому что интерфейс org.slf4j.Logger не помечен как java.io.Serializable. Однако все реализации логгеров SLF4J, поставляемые вместе с SLF4J, поддерживают сериализацию "из коробки". Попробуйте. Вы увидите, что это работает.

Вот выдержка из FAQ по SLF4j:

В отличие от статических переменных, переменные экземпляра переменные экземпляра сериализуются по умолчанию. Начиная с версии SLF4J 1.5.3, экземпляры логгеров экземпляры сохраняют сериализацию. Таким образом, сериализация класса-хозяина больше не больше не требует никаких специальных действий, даже если логгеры объявлены как переменные экземпляра. В предыдущих версиях, экземпляры регистраторов должны были были объявлены как переходные в главном class.

См. также http://slf4j.org/faq.html#declared_static

6
ответ дан 30 November 2019 в 16:57
поделиться

Моя первоначальная реакция состоит в том, чтобы задаться вопросом, имеет ли смысл сериализовать экземпляр Logger в вашем объекте. Когда вы десериализуете его позже, действительно ли справедливо ожидать, что среда Logger будет правильной? Я думаю, что я бы предпочел просто пойти с этим и назвать это днем:

private transient Logger logger = LoggerFactory.getLogger(this.getClass());
3
ответ дан 30 November 2019 в 16:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: