对于杰克逊,如何安全地共享一个ObjectMapper?有没有不可变的ObjectMapper?
问题描述:
映射器实例完全是线程安全的,不需要为单次使用创建映射器,但可以更改映射器的配置。对于杰克逊,如何安全地共享一个ObjectMapper?有没有不可变的ObjectMapper?
尽管ObjectMapper具有copy函数来复制基于存在映射器的自定义配置,但如果我共享映射器,并不能保证当有人想要自定义映射器时,它们将复制共享映射器。所以我想要一个不可变的映射器来共享,如果有人不小心改变了共享映射器,应该抛出一些异常。
有没有这样的事情?
答
写不可变的包装比我想象的有CGLIB
/**
* Create a immutable mapper, will hide some config change operation
*/
@SuppressWarnings("unchecked")
static <T extends ObjectMapper> T immutable(T mapper) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ObjectMapper.class);
enhancer.setCallback((InvocationHandler) (proxy, method, args) -> {
if (Modifier.isPublic(method.getModifiers())) {
// banned operation
String name = method.getName();
boolean match = name.startsWith("set") ||
name.startsWith("add") ||
name.startsWith("clear") ||
name.startsWith("disable") ||
name.startsWith("enable") ||
name.startsWith("register") ||
name.startsWith("config");
if (match) {
throw new UnsupportedOperationException(
"Can not modify the immutable mapper, copy the mapper first");
}
}
if (!method.isAccessible()) {
method.setAccessible(true);
}
return method.invoke(mapper, args);
});
return (T) enhancer.create();
}
由于配置得到映射是不可改变的容易,所以我不需要隐藏吸气。
答
一种方法是不共享ObjectMapper
实例,而是正确地配置它,然后共享由ObjectMapper
创建的ObjectWriter
和ObjectReader
实例。
ObjectMapper om = new ObjectMapper();
// Configure to your needs
om.enable(...);
om.disable(...);
// Distribute these to the parts of the program where you fear configuration changes.
ObjectWriter writer = om.writer();
ObjectReader reader = om.reader();
这也似乎是由杰克逊的开发商青睐的办法:https://stackoverflow.com/a/3909846/13075
我将创建ObjectMapper公正公开一些必要的功能 – Jerry06
的包装,相反,我只是想隐藏一些功能为了防止配置发生变化,这似乎是非常常见的用例,是否存在这种包装?如果不是,我会为自己创建一个。 – wener
一个选项可能是共享一个ObjectWriter实例,而不是ObjectMapper。尽管我相信这不是它的预期目的,但这个类似乍一看是不变的。 – Henrik