JacksonのObjectMapperを静的フィールドとして宣言する必要がありますか?
質問
ジャクソン図書館の ObjectMapper
クラス 糸が安全であるようです.
これは、私が私を宣言すべきだということですか? ObjectMapper
このような静的フィールドとして
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
このようなインスタンスレベルのフィールドとしての代わりに?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
解決
はい、それは安全で推奨されます。
参照したページからの唯一の注意事項は、共有されたらマッパーの構成を変更できないことです。ただし、構成を変更していないため、問題ありません。構成を変更する必要がある場合は、静的ブロックからそれを行い、同様に問題ありません。
編集: (2013/10)
2.0以上で、より良い方法があることに注意することで、上記を増強することができます:使用 ObjectWriter
と ObjectReader
によって構築できるオブジェクト ObjectMapper
。それらは完全に不変のスレッドセーフです。つまり、スレッド安全性の問題を引き起こすことさえ理論的には不可能です(これはで発生する可能性があります ObjectMapper
コードがインスタンスを再構成しようとする場合)。
他のヒント
ObjectMapperはスレッドセーフですが、特にマルチスレッドアプリケーションでは、静的変数としてそれを宣言することを強く落胆させます。それが悪い習慣だからではなく、あなたがデッドロックの重いリスクを抱えているからです。私は自分の経験からそれを語っています。 WebサービスからJSONデータを取得および処理する4つの同一のスレッドを使用してアプリケーションを作成しました。スレッドダンプによると、私のアプリケーションは次のコマンドで頻繁に停止していました。
Map aPage = mapper.readValue(reader, Map.class);
それに加えて、パフォーマンスは良くありませんでした。 Static変数をインスタンスベースの変数に置き換えると、失速が消え、パフォーマンスが4倍になりました。 IE 24分のJSON文書は、前に2.5時間ではなく、40分で56秒で処理されました。
スレッドの安全性の観点から静的オブジェクトマッパーを宣言することは安全ですが、Javaで静的オブジェクト変数を構築することは悪い練習と見なされることに注意する必要があります。詳細については、参照してください 静的変数が悪と見なされるのはなぜですか? (そして、あなたが望むなら、 私の答え)
要するに、簡潔なユニットテストを作成することを難しくするため、静的は避けるべきです。たとえば、静的な最終的なObjectMapperを使用すると、JSONシリアル化をダミーコードまたはNO-OPに交換することはできません。
さらに、静的な決勝では、実行時にObjectMapperを再構成することができなくなります。あなたは今その理由を想像していないかもしれませんが、あなたが自分自身を静的な最終パターンに閉じ込めるならば、クラスローダーを引き裂く以外に、それを再開させることができます。
ObjectMapperの場合、それは罰金ですが、一般的には悪い習慣であり、シングルトンパターンまたは逆の反転を使用して長寿命のオブジェクトを管理することよりも利点はありません。
これから私が学んだトリック Pr 静的な最終変数として定義したくないが、オーバーヘッドを少し保存して、スレッドを安全に保証したい場合。
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();
}
著者のクレジット。
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)
メソッド_hashmapsuperinterfacechain in class com.fasterxml.jackson.databind.type.typefactory 同期されます。高負荷で同じことについて競合を見ています。
静的オブジェクトマッパーを避けるもう1つの理由かもしれません