Question

La classe ObjectMapper de la bibliothèque Jackson semble être thread-safe .

Est-ce que cela signifie que je dois déclarer mon ObjectMapper comme un champ statique comme celui-ci

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

au lieu comme un champ niveau de l'instance comme celui-ci?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}
Était-ce utile?

La solution

Oui, qui est sûr et recommandé.

La seule mise en garde de la page dont vous avez parlé est que vous ne pouvez pas être en train de modifier la configuration du mappeur une fois qu'elle est partagée; mais vous ne changez pas la configuration si c'est très bien. Si vous avez besoin de changer la configuration, vous le faites à partir du bloc statique et il serait bien aussi.

modifier : (2013/10)

2,0 et au-dessus, au-dessus peut être augmentée en faisant remarquer qu'il y a une meilleure façon: l'utilisation des objets ObjectWriter et ObjectReader, qui peuvent être construits par ObjectMapper. Ils sont entièrement immuables, thread-safe, ce qui signifie qu'il est même pas théoriquement possible de poser des problèmes de sécurité des threads (qui peut se produire avec ObjectMapper si le code tente d'exemple reconfigurer).

Autres conseils

Bien que ObjectMapper est sûr de fil, je déconseillons fortement de déclarer comme une variable statique, en particulier dans l'application multithread. Pas même parce qu'il est une mauvaise pratique, mais parce que vous utilisez un risque lourd d'interblocage. Je dis cela de ma propre expérience. Je créé une application avec 4 fils identiques qui ont été d'obtenir et de traitement de données JSON de services Web. Ma demande stagnait souvent sur la commande suivante, d'après le vidage de fil:

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

A côté de cela, la performance n'a pas été bonne. Lorsque je l'ai remplacé variable statique avec la variable à base d'exemple, Stabulation disparu et la performance multiplié par quatre. C'est à dire. 2.4 millions de documents ont été traités en JSON 40min.56sec., Au lieu de 2,5 heures auparavant.

Bien qu'il soit sûr de déclarer une ObjectMapper de statique en termes de sécurité de fil, vous devez savoir que la construction des variables d'objets statiques en Java est considéré comme une mauvaise pratique. Pour plus de détails, voir Pourquoi variables statiques considérées comme mal (et si vous le souhaitez, my réponse )

En bref, il faut éviter statics parce que la il est difficile d'écrire des tests unitaires concis. Par exemple, avec une ObjectMapper finale statique, vous ne pouvez pas échanger la sérialisation JSON pour le code factice ou no-op.

En outre, un vous empêche static final de jamais reconfigurant ObjectMapper lors de l'exécution. Vous ne pourriez pas imaginer une raison pour cela, mais si vous vous enfermer dans un motif final statique, court rien démolissant la classloader vous laisser ré-initialiser.

Dans le cas de ObjectMapper son amende, mais en général il est une mauvaise pratique et il n'y a aucun avantage par rapport à l'aide d'un motif de singleton ou inversion de contrôle pour gérer vos objets à long terme.

Un truc que j'appris de cette PR si vous ne voulez pas de définir comme une variable statique finale mais que vous souhaitez économiser un peu de sécurité de fil au-dessus et de garantie.

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

crédit à l'auteur.

com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)

com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
  com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
     com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
        com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
           com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
              com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
                 com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
                    com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)

La méthode _hashMapSuperInterfaceChain dans la classe com.fasterxml.jackson.databind.type.TypeFactory est synchronisé. Voit affirmation sur le même à des charges élevées.

Peut être une autre raison d'éviter une ObjectMapper statique

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top