Должен ли журнал быть приватным статическим или нет

Должен ли логгер быть объявлен статическим или нет? Обычно я видел два типа декларации для регистратора:

    protected Log log = new Log4JLogger(aClass.class);

или

    private static Log log = new Log4JLogger(aClass.class);

Какой из них следует использовать? что такое pro и con обоих?

Ответ 1

Преимущество нестатической формы заключается в том, что вы можете объявить ее в (абстрактном) базовом классе, как следует, не беспокоясь о том, что будет использоваться правое имя класса:

protected Log log = new Log4JLogger(getClass());

Однако его недостаток, очевидно, в том, что для каждого экземпляра класса будет создан целый новый экземпляр журнала. Это, пожалуй, само по себе не дорого, но это создает значительные накладные расходы. Если вы хотите избежать этого, вы хотели бы использовать форму static. Но его недостатком является, в свою очередь, то, что вы должны объявить его в каждом отдельном классе и заботиться о каждом классе, что правильное имя класса используется во время построения журнала, потому что getClass() не может использоваться в статическом контексте. Однако в средней среде IDE вы можете создать для этого шаблон автозаполнения. Например. logger + ctrl+space.

С другой стороны, если вы получите регистратор с помощью factory, который, в свою очередь, может кэшировать уже созданные экземпляры журналов, то использование нестатической формы не добавит слишком много служебных данных. Например, для этой цели Log4j имеет LogManager.

protected Log log = LogManager.getLogger(getClass());

Ответ 2

Раньше я думал, что все логгеры должны быть статичными; однако эта статья на wiki.apache.org поднимает некоторые важные проблемы с памятью, касающиеся утечек из загрузчика классов. Объявление логгера как статического предотвращает сбор мусора в классе (и связанных с ним загрузчиках классов) в контейнерах J2EE, которые используют общий загрузчик классов. Это приведет к ошибкам PermGen, если вы повторно развернете свое приложение достаточно.

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

Ответ 3

Самое важное отличие заключается в том, как оно влияет на ваши файлы журналов: в какой категории идут журналы?

  • В вашем первом выборе журналы подкласса попадают в категорию суперкласса. Это кажется мне очень интуитивным.
  • Существует вариант вашего первого случая:

    protected Log log = new Log4JLogger (getClass());

    В этом случае ваша категория журнала указывает, на каком объекте работает код, который был зарегистрирован.

  • В вашем втором выборе (private static) категория журнала - это класс, содержащий код ведения журнала. Так обычно класс, который выполняет то, что регистрируется.

Я бы настоятельно рекомендовал последний вариант. Он имеет эти преимущества по сравнению с другими решениями:

  • Существует прямая связь между журналом и кодом. Легко найти назад, откуда пришло сообщение журнала.
  • Если кто-то должен настраивать уровни ведения журнала (что делается для каждой категории), это обычно потому, что они заинтересованы (или нет) в некоторых конкретных сообщениях, написанных определенным классом. Если категория не является классом, который пишет сообщения, сложнее настроить уровни.
  • Вы можете входить в статические методы
  • Журналистам нужно только инициализировать (или искать) один раз за класс, поэтому при запуске вместо каждого созданного экземпляра.

У него также есть недостатки:

  • Он должен быть объявлен в каждом классе, где вы регистрируете сообщения (повторное использование журналов суперкласса).
  • При инициализации регистратора вам необходимо поместить правильное имя класса. (Но хорошая IDE позаботится об этом для вас).

Ответ 4

Используйте инверсию управления и передайте регистратор в конструктор. Если вы создадите логгер внутри класса, у вас будет дьявол времени с вашими модульными тестами. Вы пишете модульные тесты, не так ли?