2009-05-18 75 views
2

我的任務是重構一些使用xmlbeans來使用jaxb的組件。一切都很順利,直到我到達一個前一位作者稱之爲copy() function of one of the XmlObjects的地方。由於xmlbeans中的所有對象都擴展了XmlObject,因此我們可以免費獲得魔法深層複製功能。如何製作像xmlbean XmlObject.copy()這樣的JAXB對象的深層副本?

Jaxb似乎沒有爲我們提供這個。什麼是正確和簡單的方法來製作一個Jaxb對象的深層副本?

+0

我很好奇,想了解爲什麼你從XMLBeans的移動到JAXB,我們使用XMLBeans,並已考慮到它比較JIXB,看看我們是否能夠得到一些性能優勢,你的動機是什麼? – Tom 2009-05-18 19:57:48

+0

好,有幾個原因,主要原因是xmlbeans enum支持有點簡單,生成的代碼接口有點奇怪,所有對象都擴展了XmlObject,我們希望生成的類完全獨立於任何東西不包括在標準的java中。所有這一切,Jaxb不包括在基礎jdk中。 – 2009-05-18 20:35:14

回答

3

您可以使您的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(); 
+0

因爲JAXB背後的全部目的是將對象與XML進行編組,所以您並不需要使它們可序列化。您可以編制並取消創建副本的對象,但這可能比編寫自己的clone()函數效率低得多。 – nsayer 2009-05-18 20:25:46

+0

+1我認爲這是正確的方式 - 它與我見過的其他建議一起討論。感謝您的示例代碼。 – 2009-05-18 20:32:33

+0

值得一提的是,這個解決方案中直接使用Object.clone()會有一些[不可忽略的開銷](http://stackoverflow.com/a/10870833/521799)。如果性能很重要,應該避免這種情況... – 2012-09-02 09:53:09

3

可以聲明使用的XSD註釋生成的JAXB對象的基類...

<xsd:annotation> 
    <xsd:appinfo> 
    <jaxb:globalBindings> 
     <xjc:superClass name="com.foo.types.support.JaxbBase" /> 
    </jaxb:globalBindings> 
    </xsd:appinfo> 
</xsd:annotation> 

您可以在那裏添加clonability支持使用xmlbeans基類作爲模板。

3

您可以使用JAXBSource

假設您想深度複製Foo類型的sourceObject。 對於同一類型的創建2個JAXBContexts:

JAXBContext sourceJAXBContext = JAXBContext.newInstance("Foo.class"); 
JAXBContext targetJAXBContext = JAXBContext.newInstance("Foo.class"); 

然後執行:

targetJAXBContext.createUnmarshaller().unmarshal(
    new JAXBSource(sourceJAXBContext,sourceObject); 
5

你可以參考這個

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()); 
} 

這對我的作品。

全部歸功於https://gist.github.com/darrend/821410