我尝试将一些基于 Apache 摘要器的 XML 序列化代码迁移到 JAXB,但结果很差。是否有关于此设计模式的最佳实践的一些建议(或放弃 JAXB 与此...)?
XML 在很大程度上依赖于接口(interface)和反射声明。
<someContainer>
<someChild class="foo.Class1">
</someChild>
</someContainer>
我使用带有此解码代码的适配器解决了间接问题
public ResultType unmarshal(Object object) throws Exception {
Element element = (Element) object;
String classname = element.getAttribute("class");
Class clazz = Class.forName(classname);
JAXBContext jc = getContext(clazz);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Object result = unmarshaller.unmarshal(element, clazz);
if (result instanceof JAXBElement) {
return (ResultType) ((JAXBElement) result).getValue();
}
return (ResultType) result;
}
好吧,即使使用 JAXBContext 缓存,这也到目前为止优于基于摘要的代码(在这一点上没有确切的衡量标准,可以说大约 50 到 100 倍)。实际性能损失的主要原因似乎在于解码的“元素”参数。大部分时间花在创建一个新的 DocumentBuilder 环境上,需要重新转换已经解析过的 Element
有什么建议吗?
最佳答案
我做了很多这样的事情,不能提示糟糕的 JAXB 性能,这在我的案例中是重中之重。在相当慢的服务器上,对于 5kb 的有效负载,完全相同的任务只需要 3-4 毫秒。至于缓存,我通常会为您的案例采用以下用于编码/解码的双向数据结构:
Map<String, MarshallData> marshalCache;
public ResultType unmarshal(Object object) throws Exception {
Element element = (Element) object;
MarshallData md = marshalCache.get(element.getAttribute("class"));
Object result = md.unmarshaller.unmarshal(element);
if (result instanceof JAXBElement) {
return (ResultType) ((JAXBElement) result).getValue();
}
return (ResultType) result;
}
public void registerMarshallData(Class clazz) throws Exception {
JAXBContext jbc = JAXBContext.newInstance(clazz); // or get it somewhere else if needed
MarshallData mdata = new MarshallData(jbc.createMarshaller(), jbc.createUnmarshaller());
marshalCache.put(clazz.getName(), mdata);
}
class MarshallData {
private Unmarshaller unmarshaller;
private Marshaller marshaller;
protected MarshallData(Marshaller marshaller, Unmarshaller unmarshaller) {
this.marshaller = marshaller;
this.unmarshaller = unmarshaller;
}
}
关于java - "generic"用例的 JAXB 性能不佳 - 更好的设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9739063/