Да, это безопасно и рекомендуется.
Единственное предостережение на странице, на которую вы ссылались, это то, что вы не можете изменять конфигурацию маппера, как только он будет опубликован; но вы не меняете конфигурацию, так что все в порядке. Если вам нужно изменить конфигурацию, вы сделаете это из статического блока, и это будет хорошо.
РЕДАКТИРОВАТЬ : (2013/10)
С 2.0 и выше, выше можно дополнить, отметив, что есть еще лучший способ: использовать ObjectWriter
и ObjectReader
объекты, которые могут быть сконструированы ObjectMapper
. Они являются полностью неизменяемыми, поточно-ориентированными, что означает, что теоретически невозможно вызвать проблемы с безопасностью потоков (которые могут возникнуть, ObjectMapper
если код попытается перенастроить экземпляр).
ObjectMapper
после вызова вызывается потокобезопасностьObjectMapper#setDateFormat()
. Известно, чтоSimpleDateFormat
не является потокобезопасным , поэтомуObjectMapper
не будет, если не будет клонироваться, например,SerializationConfig
перед каждымwriteValue()
(я сомневаюсь). Не могли бы вы развенчать мой страх?DateFormat
действительно клонируется под капотом. Хорошие подозрения там, но вы прикрыты. :)ObjectMapper
?! Методы названыwriter()
иreader()
(и некоторыеreaderFor()
,writerFor()
).mapper.with()
(так как «с» в Джексоне подразумевает создание нового экземпляра и выполнение с поддержкой потоков). Но что касается изменений конфигурации: проверка не производится, поэтому доступ к конфигурацииObjectMapper
должен быть защищен. Что касается «copy ()»: да, это создает новую новую копию, которая может быть полностью (пере) настроена в соответствии с теми же правилами: сначала полностью сконфигурируйте ее, затем используйте, и это нормально. Это связано с нетривиальными затратами (поскольку копирование не может использовать ни один из кэшированных обработчиков), но это безопасный способ, да.Хотя ObjectMapper является потокобезопасным, я бы настоятельно не рекомендовал объявлять его статической переменной, особенно в многопоточных приложениях. Даже не потому, что это плохая практика, а потому, что вы подвергаетесь серьезному риску взаимоблокировки. Я говорю это на собственном опыте. Я создал приложение с 4 одинаковыми потоками, которые получали и обрабатывали данные JSON из веб-сервисов. Мое приложение часто зависало по следующей команде, согласно дампу потока:
Кроме того, производительность не была хорошей. Когда я заменил статическую переменную на переменную, основанную на экземпляре, задержка исчезла, а производительность увеличилась в четыре раза. Т.е. 2,4 миллиона документов JSON были обработаны за 40 минут 56 секунд, вместо 2,5 часов ранее.
источник
ObjectMapper
экземпляра для каждого экземпляра класса может предотвратить блокировки, но позже может привести к большим нагрузкам на GC (представьте один экземпляр ObjectMapper для каждого экземпляра создаваемого вами класса). Подход со средним путем может заключаться в том, что вместо сохранения одного (открытого) статическогоObjectMapper
экземпляра в приложении вы можете объявить (частный) статический экземплярObjectMapper
каждого класса . Это уменьшит глобальную блокировку (за счет распределения нагрузки по классам) и не создаст никакого нового объекта, а значит, и GC.ObjectPool
- это лучший способ, которым вы можете следовать, тем самым обеспечивая лучшееGC
иLock
производительность. Вы можете обратиться к следующей ссылке для реализации apache-commonObjectPool
. commons.apache.org/proper/commons-pool/api-1.6/org/apache/…ObjectMapper
где-то сохранять статичность , но только получатьObjectReader
/ObjectWriter
экземпляры (через вспомогательные методы), сохранять ссылки на них в других местах (или динамически вызывать). Эти объекты чтения / записи являются не только полностью поточно-ориентированными при реконфигурации, но и очень легкими (в случае экземпляров mapper). Таким образом, хранение тысяч ссылок не увеличивает объем используемой памяти.Хотя можно объявить статический ObjectMapper с точки зрения безопасности потоков, вы должны знать, что создание статических переменных Object в Java считается плохой практикой. Подробнее см. Почему статические переменные считаются злыми? (и, если хотите, мой ответ )
Короче говоря, статики следует избегать, потому что это затрудняет написание кратких модульных тестов. Например, со статическим финальным ObjectMapper вы не можете поменять сериализацию JSON на фиктивный код или неработоспособность.
Кроме того, статический финал не позволяет вам когда-либо реконфигурировать ObjectMapper во время выполнения. Вы можете и не представить себе причину этого сейчас, но если вы заблокируете себя в статическом окончательном шаблоне, ничто кроме разрушения загрузчика классов не позволит вам повторно инициализировать его.
В случае ObjectMapper это хорошо, но в целом это плохая практика, и нет никакого преимущества в использовании одноэлементного шаблона или инверсии управления для управления вашими долгоживущими объектами.
источник
readerFor
иwriterFor
которые создаютObjectReader
иObjectWriter
экземпляры по требованию. Так что я бы сказал, что поместите маппер с исходной конфигурацией где-нибудь в статическом состоянии, а затем получите читателей / писателей с конфигурацией для каждого конкретного случая, как вам нужно?Уловка, которую я узнал из этого PR, если вы не хотите определять ее как статическую конечную переменную, но хотите сэкономить немного ресурсов и гарантировать безопасность потока.
кредит автору.
источник
ObjectMapper
он будет присоединен к потоку, который может быть частью пула.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
Метод _hashMapSuperInterfaceChain в классе com.fasterxml.jackson.databind.type.TypeFactory синхронизируется. Увижу раздоры на том же при высоких нагрузках.
Может быть еще одна причина, чтобы избежать статического ObjectMapper
источник
TypeReference
довольно дорогая вещь: если возможно, ее разрешениеJavaType
позволит избежать значительной обработки (TypeReference
к сожалению, ее нельзя кэшировать по причинам, которые я здесь не буду изучать), поскольку они «полностью разрешены» (супер-тип, универсальная типизация и т. д.).