Tak, jest to bezpieczne i zalecane.
Jedynym zastrzeżeniem ze strony, do której się odwoływałeś, jest to, że nie możesz modyfikować konfiguracji mapera po jego udostępnieniu; ale nie zmieniasz konfiguracji, więc nie ma sprawy. Gdybyś musiał zmienić konfigurację, zrobiłbyś to z bloku statycznego i byłoby dobrze.
EDYCJA : (2013/10)
W wersji 2.0 i nowszej powyższe można rozszerzyć, zauważając, że istnieje jeszcze lepszy sposób: użycie ObjectWriter
i ObjectReader
obiekty, które można zbudować ObjectMapper
. Są w pełni niezmienne, bezpieczne dla wątków, co oznacza, że teoretycznie nie jest możliwe spowodowanie problemów z bezpieczeństwem wątków (co może się zdarzyć, ObjectMapper
jeśli kod spróbuje ponownie skonfigurować instancję).
ObjectMapper
poObjectMapper#setDateFormat()
wywołaniu nadal jest bezpieczny dla wątków . Wiadomo, żeSimpleDateFormat
nie jest bezpieczny dla wątków , a więcObjectMapper
nie będzie, dopóki nie sklonuje np.SerializationConfig
Przed każdymwriteValue()
(wątpię). Czy możesz obalić mój strach?DateFormat
jest rzeczywiście sklonowany pod maską. Dobre podejrzenia, ale jesteś objęty ochroną. :)ObjectMapper
w ogóle na ciebie patrzyłeś ?! Metody są nazwanewriter()
ireader()
(a niektórereaderFor()
,writerFor()
).mapper.with()
wywołania (ponieważ „z” w Jacksonie oznacza budowę nowej instancji i wykonanie bezpieczne dla wątków). Ale w odniesieniu do zmian w konfiguracji: nie dokonuje się sprawdzania, więc dostęp do konfiguracjiObjectMapper
musi być chroniony. Jeśli chodzi o „copy ()”: tak, to tworzy nową, nową kopię, która może być w pełni (ponownie) skonfigurowana zgodnie z tymi samymi regułami: najpierw ją najpierw skonfiguruj, a potem użyj i wszystko jest w porządku. Powiązane są nietrywialne koszty (ponieważ kopia nie może korzystać z żadnej z buforowanych procedur obsługi), ale jest to bezpieczny sposób, tak.Chociaż ObjectMapper jest bezpieczny dla wątków, zdecydowanie odradzałbym deklarowanie go jako zmiennej statycznej, szczególnie w aplikacjach wielowątkowych. Nawet dlatego, że jest to zła praktyka, ale ponieważ istnieje duże ryzyko zakleszczenia. Mówię to z własnego doświadczenia. Stworzyłem aplikację z 4 identycznymi wątkami, które pobierały i przetwarzały dane JSON z usług internetowych. Moja aplikacja często zwlekała z następującą komendą, zgodnie ze zrzutem wątku:
Poza tym wydajność nie była dobra. Kiedy zastąpiłem zmienną statyczną zmienną opartą na instancji, przeciągnięcie zniknęło, a wydajność czterokrotnie. To znaczy 2,4 miliona dokumentów JSON zostało przetworzonych w 40 minut 56 sekund, zamiast 2,5 godziny wcześniej.
źródło
ObjectMapper
instancji dla każdej instancji klasy może zapobiegać blokadom, ale może być naprawdę ciężkie dla GC później (wyobraź sobie jedną instancję ObjectMapper dla każdej instancji tworzonej klasy). Podejściem środkowej ścieżki może być, zamiast utrzymywania tylko jednej (publicznej)ObjectMapper
instancji statycznej w aplikacji, możesz zadeklarować (prywatną) instancję statycznąObjectMapper
w każdej klasie . Zmniejszy to globalną blokadę (poprzez dystrybucję obciążenia według klasy obciążenia) i nie stworzy też żadnego nowego obiektu, stąd też światło na GC.ObjectPool
jest najlepszym sposobem, w jaki możesz iść - tym samym dając najlepszeGC
iLock
występy. Możesz zapoznać się z poniższym linkiem doObjectPool
implementacji apache-common . commons.apache.org/proper/commons-pool/api-1.6/org/apache/…ObjectMapper
gdzieś statyczny , ale tylko getObjectReader
/ObjectWriter
instancje (za pomocą metod pomocniczych), zachowuj odniesienia do tych w innych miejscach (lub dynamicznie wywołuj). Te obiekty do odczytu / zapisu są nie tylko w pełni bezpieczne dla wątków rekonfiguracji wrt, ale także bardzo lekkie (instancje wrt mapper). Zachowanie tysięcy referencji nie powoduje dużego zużycia pamięci.Chociaż deklarowanie statycznego obiektu ObjectMapper jest bezpieczne pod względem bezpieczeństwa wątków, należy pamiętać, że konstruowanie statycznych zmiennych Object w Javie jest uważane za złą praktykę. Aby uzyskać więcej informacji, zobacz Dlaczego zmienne statyczne są uważane za złe? (a jeśli chcesz, moja odpowiedź )
Krótko mówiąc, należy unikać statyki, ponieważ utrudniają pisanie zwięzłych testów jednostkowych. Na przykład przy statycznym ostatecznym ObjectMapper nie można zamienić serializacji JSON na kod fikcyjny lub brak operacji.
Ponadto statyczny finał uniemożliwia kiedykolwiek ponowną konfigurację ObjectMapper w czasie wykonywania. Być może nie wyobrażasz sobie teraz powodu, ale jeśli zablokujesz się w statycznym ostatecznym wzorze, nic poza wyburzeniem programu ładującego klasy nie pozwoli ci go ponownie zainicjować.
W przypadku ObjectMapper jest to w porządku, ale ogólnie jest to zła praktyka i nie ma przewagi nad użyciem wzorca singletonu lub odwrócenia kontroli do zarządzania długowiecznymi obiektami.
źródło
readerFor
iwriterFor
które tworząObjectReader
iObjectWriter
wystąpienia na żądanie. Więc powiedziałbym, żeby umieścić program mapujący z początkową konfiguracją gdzieś statycznie, a następnie uzyskać czytelników / pisarzy z konfiguracją dla poszczególnych skrzynek, jeśli ich potrzebujesz?Sztuczka, której nauczyłem się z tego PR, jeśli nie chcesz zdefiniować jej jako statycznej zmiennej końcowej, ale chcesz zaoszczędzić trochę narzutów i zagwarantować bezpieczeństwo wątku.
podziękowania dla autora.
źródło
ObjectMapper
zostanie on dołączony do wątku, który może być częścią puli.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
Metoda _hashMapSuperInterfaceChain w klasie com.fasterxml.jackson.databind.type.TypeFactory jest zsynchronizowana. Widzę spór o to samo przy dużych obciążeniach.
Może być kolejnym powodem do uniknięcia statycznego ObjectMapper
źródło
TypeReference
jest to nieco kosztowna rzecz w użyciu: jeśli to możliwe, rozwiązanie jejJavaType
pozwoli uniknąć sporo przetwarzania (TypeReference
nie można - niestety - buforować z powodów, których nie będę tu kopać), ponieważ one są „w pełni rozwiązane” (super-type, ogólne pisanie itp.).