杰克逊图书馆的 ObjectMapper 班级 似乎是安全的.

这是否意味着我应该宣布我的 ObjectMapper 作为这样的静态领域

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

而不是像这样的实例级字段?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}
有帮助吗?

解决方案

是的,这是安全的建议。

您引用的页面中唯一的警告是,一旦共享映射器,就无法修改对映射器的配置;但是您没有更改配置,所以很好。如果您确实需要更改配置,则可以从静态块中执行此操作,也可以。

编辑: (2013/10)

使用2.0及以上,可以通过指出有更好的方法来增强上述:使用 ObjectWriterObjectReader 对象,可以由 ObjectMapper。它们是完全不可变的,螺纹安全的,这意味着在理论上甚至都不可能引起线程安全问题(这可能会发生 ObjectMapper 如果代码试图重新配置实例)。

其他提示

尽管ObjectMapper是线程安全的,但我强烈建议将其声明为静态变量,尤其是在多线程应用程序中。甚至不是因为这是一种不好的做法,而是因为您承受着僵局的严重风险。我是根据自己的经验告诉它。我创建了一个使用4个相同线程的应用程序,这些线程正在从Web服务中获取和处理JSON数据。根据线程转储,我的应用程序经常停滞在以下命令上:

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

除此之外,性能不好。当我用基于实例的变量替换静态变量时,失速消失了,性能四倍。 IE在40分钟内处理了2400万个JSON文档,而不是前2.5小时。

尽管可以从线程安全性方面宣布静态对象贴,但您应该意识到,在Java中构建静态对象变量被认为是不良实践。有关更多详细信息,请参阅 为什么静态变量被认为是邪恶的? (如果您愿意, 我的答案)

简而言之,应该避免使用静态,因为很难编写简洁的单位测试。例如,使用静态的最终对象拍摄器,您无法将JSON序列化换成虚拟代码或NO-OP。

此外,静态决赛可防止您在运行时重新配置ObjectMapper。您现在可能不会设想出这样的原因,但是如果您将自己锁定在静态的最终模式中,那么拆除classloader就可以让您重新定位它。

对于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(eshierarchictype)

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在类中 com.fasterxml.jackson.databind.type.typefactory 已同步。在高载荷下看到同一的争论。

可能是避免静态对象拍摄器的另一个原因

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top