Ja, das ist sicher und empfohlen.
Die einzige Einschränkung auf der Seite, auf die Sie verwiesen haben, ist, dass Sie die Konfiguration des Mappers nicht mehr ändern können, sobald er freigegeben ist. Sie ändern jedoch nicht die Konfiguration, sodass dies in Ordnung ist. Wenn Sie die Konfiguration ändern müssten, würden Sie dies über den statischen Block tun, und es wäre auch in Ordnung.
EDIT : (2013/10)
Ab 2.0 kann das oben Gesagte erweitert werden, indem festgestellt wird, dass es einen noch besseren Weg gibt: Verwendung ObjectWriter
und ObjectReader
Objekte, die von konstruiert werden können ObjectMapper
. Sie sind vollständig unveränderlich, threadsicher, was bedeutet, dass es theoretisch nicht einmal möglich ist, Thread-Sicherheitsprobleme zu verursachen (die auftreten können, ObjectMapper
wenn Code versucht, die Instanz neu zu konfigurieren).
ObjectMapper
nach demObjectMapper#setDateFormat()
Aufruf noch threadsicher ist. Es ist bekannt, dass diesSimpleDateFormat
nicht threadsicher ist und daherObjectMapper
nicht möglich ist, es sei denn, es klont zBSerializationConfig
vor jedemwriteValue()
(ich bezweifle). Könnten Sie meine Angst entlarven?DateFormat
ist in der Tat unter der Haube geklont. Guter Verdacht dort, aber Sie sind abgesichert. :)ObjectMapper
überhaupt ?! Methoden werden benanntwriter()
undreader()
(und einigereaderFor()
,writerFor()
).mapper.with()
Aufruf (da "with" in Jackson die Erstellung einer neuen Instanz und die thread-sichere Ausführung impliziert). Aber bezüglich Konfigurationsänderungen: Es wird keine Überprüfung durchgeführt, daher muss der Konfigurationszugriff aufObjectMapper
geschützt werden. Zu "copy ()": Ja, das erstellt eine neue Kopie, die nach denselben Regeln vollständig (neu) konfiguriert werden kann: zuerst vollständig konfigurieren, dann verwenden, und das ist in Ordnung. Es sind nicht triviale Kosten verbunden (da die Kopie keinen der zwischengespeicherten Handler verwenden kann), aber dies ist der sichere Weg, ja.Obwohl ObjectMapper threadsicher ist, würde ich dringend davon abraten, es als statische Variable zu deklarieren, insbesondere in Multithread-Anwendungen. Nicht einmal, weil es eine schlechte Praxis ist, sondern weil Sie ein hohes Risiko eines Deadlocks haben. Ich erzähle es aus meiner eigenen Erfahrung. Ich habe eine Anwendung mit 4 identischen Threads erstellt, die JSON-Daten von Webdiensten abrufen und verarbeiten. Meine Anwendung wurde laut Thread-Dump häufig mit dem folgenden Befehl blockiert:
Außerdem war die Leistung nicht gut. Als ich die statische Variable durch die instanzbasierte Variable ersetzte, verschwand das Abwürgen und die Leistung vervierfachte sich. Dh 2,4 Millionen JSON-Dokumente wurden in 40 Minuten, 56 Sekunden anstatt 2,5 Stunden zuvor verarbeitet.
quelle
ObjectMapper
Instanz für jede Klasseninstanz kann jedoch Sperren verhindern, kann aber später die GC erheblich belasten (stellen Sie sich eine ObjectMapper-Instanz für jede Instanz der von Ihnen erstellten Klasse vor). Ein Ansatz mit mittlerem Pfad kann darin bestehen, dass Sie nicht nur eine (öffentliche) statischeObjectMapper
Instanz in der Anwendung behalten, sondern in jeder Klasse eine (private) statische Instanz deklarieren können . Dies reduziert eine globale Sperre (durch Verteilung der Lastklasse) und erstellt auch kein neues Objekt, wodurch auch die GC beleuchtet wird.ObjectMapper
ObjectPool
der beste Weg, den Sie gehen können - und damit das BesteGC
und die bestenLock
Leistungen zu erzielen. Sie können auf den folgenden Link für dieObjectPool
Implementierung von Apache-Common verweisen . commons.apache.org/proper/commons-pool/api-1.6/org/apache/…ObjectMapper
irgendwo statisch bleiben , aber nurObjectReader
/ObjectWriter
Instanzen abrufen (über Hilfsmethoden), Verweise auf solche an anderen Stellen beibehalten (oder dynamisch aufrufen). Diese Reader / Writer-Objekte sind nicht nur vollständig threadsicher für die Rekonfiguration, sondern auch sehr leicht (Wrt-Mapper-Instanzen). Das Speichern von Tausenden von Referenzen führt also nicht zu einer hohen Speichernutzung.Obwohl es sicher ist, einen statischen ObjectMapper im Hinblick auf die Thread-Sicherheit zu deklarieren, sollten Sie sich bewusst sein, dass das Erstellen statischer Objektvariablen in Java als schlechte Praxis angesehen wird. Weitere Informationen finden Sie unter Warum werden statische Variablen als böse angesehen? (und wenn Sie möchten, meine Antwort )
Kurz gesagt, Statik sollte vermieden werden, da dies das Schreiben präziser Komponententests erschwert. Beispielsweise können Sie mit einem statischen endgültigen ObjectMapper die JSON-Serialisierung nicht gegen Dummy-Code oder ein No-Op austauschen.
Darüber hinaus verhindert ein statisches Finale, dass Sie ObjectMapper zur Laufzeit neu konfigurieren können. Sie können sich jetzt vielleicht keinen Grund dafür vorstellen, aber wenn Sie sich in ein statisches endgültiges Muster einschließen, können Sie es durch Herunterfahren des Klassenladeprogramms neu initialisieren.
Im Fall von ObjectMapper ist es in Ordnung, aber im Allgemeinen ist es eine schlechte Praxis und es gibt keinen Vorteil gegenüber der Verwendung eines Singleton-Musters oder einer Umkehrung der Kontrolle, um Ihre langlebigen Objekte zu verwalten.
quelle
readerFor
undwriterFor
welche erstellenObjectReader
undObjectWriter
Instanzen bei Bedarf. Also würde ich sagen, setzen Sie den Mapper mit der anfänglichen Konfiguration an einen statischen Ort und holen Sie sich dann Leser / Schreiber mit der Konfiguration pro Fall, wenn Sie sie benötigen?Ein Trick, den ich aus dieser PR gelernt habe, wenn Sie sie nicht als statische Endvariable definieren, sondern ein wenig Overhead sparen und Thread-Sicherheit gewährleisten möchten.
Gutschrift an den Autor.
quelle
ObjectMapper
dieser an den Thread angehängt wird, der möglicherweise Teil eines Pools ist.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
Die Methode _hashMapSuperInterfaceChain in der Klasse com.fasterxml.jackson.databind.type.TypeFactory wird synchronisiert. Ich sehe Streit um das gleiche bei hohen Lasten.
Kann ein weiterer Grund sein, einen statischen ObjectMapper zu vermeiden
quelle
TypeReference
etwas teuer ist, es zu verwenden: Wenn möglich, würde das AuflösenJavaType
einiges an Verarbeitung vermeiden (TypeReference
s können - leider - aus Gründen, auf die ich hier nicht näher eingehen werde, nicht zwischengespeichert werden), da sie sind "vollständig aufgelöst" (Supertyp, generische Typisierung usw.).