我的任務是重構一些使用xmlbeans來使用jaxb的組件。一切都很順利,直到我到達一個前一位作者稱之爲copy() function of one of the XmlObjects的地方。由於xmlbeans中的所有對象都擴展了XmlObject,因此我們可以免費獲得魔法深層複製功能。如何製作像xmlbean XmlObject.copy()這樣的JAXB對象的深層副本?
Jaxb似乎沒有爲我們提供這個。什麼是正確和簡單的方法來製作一個Jaxb對象的深層副本?
我的任務是重構一些使用xmlbeans來使用jaxb的組件。一切都很順利,直到我到達一個前一位作者稱之爲copy() function of one of the XmlObjects的地方。由於xmlbeans中的所有對象都擴展了XmlObject,因此我們可以免費獲得魔法深層複製功能。如何製作像xmlbean XmlObject.copy()這樣的JAXB對象的深層副本?
Jaxb似乎沒有爲我們提供這個。什麼是正確和簡單的方法來製作一個Jaxb對象的深層副本?
您可以使您的JAXB類可序列化,然後通過序列化和反序列化深入複製對象。該代碼可能看起來像:
Object obj = ... // object to copy
ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());
out.writeObject(obj);
byte[] bytes = baos.toByteArray();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object copy = in.readObject();
因爲JAXB背後的全部目的是將對象與XML進行編組,所以您並不需要使它們可序列化。您可以編制並取消創建副本的對象,但這可能比編寫自己的clone()函數效率低得多。 – nsayer 2009-05-18 20:25:46
+1我認爲這是正確的方式 - 它與我見過的其他建議一起討論。感謝您的示例代碼。 – 2009-05-18 20:32:33
值得一提的是,這個解決方案中直接使用Object.clone()會有一些[不可忽略的開銷](http://stackoverflow.com/a/10870833/521799)。如果性能很重要,應該避免這種情況... – 2012-09-02 09:53:09
可以聲明使用的XSD註釋生成的JAXB對象的基類...
<xsd:annotation>
<xsd:appinfo>
<jaxb:globalBindings>
<xjc:superClass name="com.foo.types.support.JaxbBase" />
</jaxb:globalBindings>
</xsd:appinfo>
</xsd:annotation>
您可以在那裏添加clonability支持使用xmlbeans基類作爲模板。
您可以使用JAXBSource
假設您想深度複製Foo類型的sourceObject。 對於同一類型的創建2個JAXBContexts:
JAXBContext sourceJAXBContext = JAXBContext.newInstance("Foo.class");
JAXBContext targetJAXBContext = JAXBContext.newInstance("Foo.class");
然後執行:
targetJAXBContext.createUnmarshaller().unmarshal(
new JAXBSource(sourceJAXBContext,sourceObject);
你可以參考這個
public static <T> T deepCopyJAXB(T object, Class<T> clazz) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, object);
JAXBSource source = new JAXBSource(jaxbContext, contentObject);
return jaxbContext.createUnmarshaller().unmarshal(source, clazz).getValue();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
public static <T> T deepCopyJAXB(T object) {
if(object==null) throw new RuntimeException("Can't guess at class");
return deepCopyJAXB(object, (Class<T>) object.getClass());
}
這對我的作品。
我很好奇,想了解爲什麼你從XMLBeans的移動到JAXB,我們使用XMLBeans,並已考慮到它比較JIXB,看看我們是否能夠得到一些性能優勢,你的動機是什麼? – Tom 2009-05-18 19:57:48
好,有幾個原因,主要原因是xmlbeans enum支持有點簡單,生成的代碼接口有點奇怪,所有對象都擴展了XmlObject,我們希望生成的類完全獨立於任何東西不包括在標準的java中。所有這一切,Jaxb不包括在基礎jdk中。 – 2009-05-18 20:35:14