Подтвердить что ты не робот

Должен ли логгер Log4J быть объявлен переходным?

Я использую Java 1.4 с Log4J.

Некоторые из моего кода включают сериализацию и десериализацию объектов значений (POJO).

Каждый из моих POJO объявляет регистратор с

private final Logger log = Logger.getLogger(getClass());

Сериализатор жалуется, что org.apache.log4j.Logger не является Serializable.

Должен ли я использовать

private final transient Logger log = Logger.getLogger(getClass());

вместо

4b9b3361

Ответ 1

Как использовать статический логгер? Или вам нужна другая справочная информация для каждого экземпляра класса? По умолчанию статические поля не сериализуются; вы можете явно объявлять поля для сериализации с частным статическим окончательным массивом ObjectStreamField с именем serialPersistentFields. См. документацию по Oracle

Добавленный контент: Когда вы используете getLogger (getClass()), вы будете использовать один и тот же регистратор в каждом экземпляре. Если вы хотите использовать отдельный регистратор для каждого экземпляра, вам нужно различать имя регистратора в методе getLogger(). например getLogger (getClass(). getName() + hashCode()). Затем вы должны использовать атрибут переходного процесса, чтобы убедиться, что регистратор не сериализуется.

Ответ 2

Регистратор должен быть статическим; это сделает его несериализуемым.

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

Ответ 3

Если вы действительно хотите перейти к временному подходу, вам понадобится reset журнал, когда ваш объект будет десериализован. Способ сделать это - реализовать метод:

 private void readObject(java.io.ObjectInputStream in) 
   throws IOException, ClassNotFoundException;

В javadocs для Serializable содержится информация об этом методе.

Ваша реализация будет выглядеть примерно так:

 private void readObject(java.io.ObjectInputStream in) 
     throws IOException, ClassNotFoundException {
   log = Logger.getLogger(...);
   in.defaultReadObject();
 }

Если вы этого не сделаете, тогда после десериализации вашего объекта журнал будет пустым.

Ответ 4

Либо объявляйте поле регистратора статичным, либо временным.

Оба способа гарантируют, что метод writeObject() не будет пытаться записать поле в выходной поток во время сериализации.

Обычно поля регистратора объявляются статическими, но если вам нужно, чтобы это поле экземпляра, просто объявляйте его временным, как обычно это делается для любого несериализуемого поля. При десериализации поле регистратора будет нулевым, поэтому вам необходимо реализовать метод readObject() для его правильной инициализации.

Ответ 5

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

Ответ 6

Эти типы случаев, особенно в EJB, обычно лучше всего обрабатываются через локальное состояние потока. Обычно вариант использования - это то, что у вас есть конкретная транзакция, которая сталкивается с проблемой, и вам нужно поднять логгинг для отладки для этой операции, чтобы вы могли генерировать подробные записи о проблеме. Перенесите какое-либо локальное состояние потока в транзакции и используйте это, чтобы выбрать правильный регистратор. Честно говоря, я не знаю, где было бы полезно установить уровень на INSTANCE в этой среде, потому что отображение экземпляров в транзакцию должно быть функцией уровня контейнера, вы фактически не будете контролировать, какой экземпляр используется в данная транзакция в любом случае.

Даже в случаях, когда вы имеете дело с DTO, обычно не рекомендуется разрабатывать вашу систему таким образом, чтобы требовался конкретный экземпляр, потому что дизайн может легко развиваться способами, которые делают этот плохой выбор, Вы можете прийти через месяц и решить, что соображения эффективности (кэширование или какая-то другая оптимизация жизненного цикла) нарушат ваше предположение о сопоставлении экземпляров с единицами работы.

Ответ 7

Если вы хотите, чтобы Logger был для каждого экземпляра, то да, вы хотели бы сделать его переходным, если вы собираетесь сериализовать свои объекты. Log4J Loggers не сериализуемы, а не в версии Log4J, которую я использую в любом случае, поэтому, если вы не измените свои поля Logger, вы получите исключения при сериализации.

Ответ 8

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

Ответ 9

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

(Как и другие, упоминалось использование статического или временного).