web-dev-qa-db-de.com

Sollte ich Jacksons ObjectMapper als statisches Feld deklarieren?

Die ObjectMapper-Klasse der Jackson-Bibliothek scheint threadsicher zu sein.

Bedeutet das, dass ich meine ObjectMapper als statisches Feld wie dieses deklarieren soll

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

statt als Instanz-Ebene-Feld wie dieses?

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

Ja, das ist sicher und empfehlenswert.

Der einzige Nachteil der von Ihnen verwiesenen Seite ist, dass Sie die Konfiguration des Mapper nicht ändern können, sobald er freigegeben wurde. Sie ändern jedoch nicht die Konfiguration, also ist das in Ordnung. Wenn Sie die Konfiguration ändern mussten, würden Sie dies vom statischen Block aus tun, und es wäre auch in Ordnung.

EDIT: (2013/10)

Mit 2.0 und höher kann Oben erwähnt werden, indem Sie feststellen, dass es einen noch besseren Weg gibt: Verwenden Sie ObjectWriter und ObjectReader-Objekte, die mit ObjectMapper..__ erstellt werden können theoretisch möglich, Thread-Sicherheitsprobleme zu verursachen (die mit ObjectMapper auftreten können, wenn Code versucht, die Instanz neu zu konfigurieren).

436
StaxMan

Obwohl ObjectMapper Thread-sicher ist, würde ich dringend davon abraten, es als statische Variable zu deklarieren, insbesondere in Multithread-Anwendungen. Nicht, weil dies eine schlechte Praxis ist, sondern weil Sie das Risiko eines Deadlocks haben. Ich erzähle es aus eigener Erfahrung. Ich habe eine Anwendung mit 4 identischen Threads erstellt, die JSON-Daten von Webservices abrufen und verarbeiten .. __ Meine Anwendung blockierte den folgenden Befehl laut Thread-Dump häufig:

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

Abgesehen davon war die Leistung nicht gut. Wenn ich die statische Variable durch die Instanzvariable ersetzte, verschwand das Stalling und die Leistung vervierfachte sich. Das heißt 2,4 Millionen JSON-Dokumente wurden in 40 Minuten und 56 Sekunden (statt 2,5 Stunden zuvor) verarbeitet.

32
Gary Greenberg

Obwohl es in Bezug auf die Thread-Sicherheit sicher ist, einen statischen ObjectMapper zu deklarieren, sollten Sie wissen, dass das Erstellen statischer Objektvariablen in Java als schlechte Praxis gilt. Weitere Informationen finden Sie unter Warum werden statische Variablen als schlecht eingestuft? (und wenn Sie möchten, meine Antwort )

Kurz gesagt, Statik sollte vermieden werden, da es schwierig ist, kompakte Komponententests zu schreiben. Mit einem statischen finalen ObjectMapper können Sie beispielsweise die JSON-Serialisierung nicht für Dummy-Code oder No-Op austauschen.

Außerdem verhindert ein statischer Abschluss, dass Sie ObjectMapper zur Laufzeit jemals neu konfigurieren müssen. Sie können sich jetzt keinen Grund dafür vorstellen, aber wenn Sie sich in ein statisches endgültiges Muster einbinden, wird der Classloader durch nichts heruntergefahren, so dass Sie ihn erneut initialisieren können.

Im Fall von ObjectMapper ist dies in Ordnung, aber im Allgemeinen ist es eine schlechte Praxis, und es ist nicht vorteilhaft, ein Singleton-Muster oder eine Umkehrung der Steuerung zum Verwalten Ihrer langlebigen Objekte zu verwenden.

2
JBCP

Ein Trick, den ich daraus gelernt habe PR , wenn Sie sie nicht als statische Endvariable definieren, sondern ein wenig Overhead sparen und Thread-Sicherheit gewährleisten möchten.

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();
}

dank an den Autor.

0
Adam Lin