it-roy-ru.com

Должен ли я объявить Джексона ObjectMapper как статическое поле?

Класс ObjectMapper библиотеки Джексона кажется потокобезопасным .

Означает ли это, что я должен объявить свой ObjectMapper как статическое поле, как это

class Me {
    private static final ObjectMapper mapper = new ObjectMapper();
}

а не как поле уровня экземпляра, как это?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}
296
Cheok Yan Cheng

Да, это безопасно и рекомендуется.

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

РЕДАКТИРОВАТЬ: (2013/10)

В версии 2.0 и выше вышеприведенное можно дополнить, отметив, что есть еще лучший способ: использовать объекты ObjectWriter и ObjectReader, которые могут быть созданы с помощью ObjectMapper. Они являются полностью неизменяемыми, поточно-ориентированными, что означает, что это даже не теоретически возможно вызвать проблемы с безопасностью потоков (которые могут возникнуть с ObjectMapper, если код пытается переконфигурировать экземпляр).

436
StaxMan

Хотя ObjectMapper является потокобезопасным, я бы настоятельно не рекомендовал объявлять его как статическую переменную, особенно в многопоточных приложениях…. Даже не потому, что это плохая практика, а потому, что у вас большой риск взаимоблокировки. Я говорю это на собственном опыте. Я создал приложение с четырьмя одинаковыми потоками, которые получали и обрабатывали данные JSON из веб-служб . Мое приложение часто зависало при выполнении следующей команды, согласно дампу потока:

Map aPage = mapper.readValue(reader, Map.class);

Кроме того, производительность была плохой ... Когда я заменил статическую переменную на переменную, основанную на экземпляре, зависание исчезло, а производительность увеличилась в четыре раза. То есть 2,4 миллиона документов JSON были обработаны за 40 минут 56 секунд, вместо 2,5 часов ранее.

32
Gary Greenberg

Хотя можно объявить статический ObjectMapper с точки зрения безопасности потоков, вы должны знать, что создание статических переменных Object в Java считается плохой практикой. Для получения более подробной информации см. Почему статические переменные считаются злыми? (и если хотите, мой ответ )

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

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

В случае ObjectMapper это хорошо, но в целом это плохая практика, и нет никакого преимущества в использовании одноэлементного шаблона или инверсии контроля для управления вашими долгоживущими объектами.

2
JBCP

Уловка, которую я узнал из этого PR , если вы не хотите определять ее как статическую конечную переменную, но хотите сэкономить немного накладных расходов и гарантировать безопасность потока.

private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
    @Override
    protected ObjectMapper initialValue() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }
};

public static ObjectMapper getObjectMapper() {
    return om.get();
}

кредит автору.

0
Adam Lin