จุดประสงค์ของคลาส ObjectFactory ของ JAXB 2 คืออะไร?


98

ฉันเพิ่งเริ่มใช้ JAXB และฉันใช้ xjc ของ JAXB 2.1.3 เพื่อสร้างชุดของคลาสจาก XML Schema ของฉัน นอกเหนือจากการสร้างคลาสสำหรับแต่ละองค์ประกอบในสคีมาของฉันแล้วยังสร้างคลาส ObjectFactory

ดูเหมือนจะไม่มีอะไรหยุดฉันจากการสร้างอินสแตนซ์องค์ประกอบโดยตรงเช่น

MyElement element = new MyElement();

ในขณะที่แบบฝึกหัดดูเหมือนจะชอบมากกว่า

MyElement element = new ObjectFactory().createMyElement();

ถ้าฉันดู ObjectFactory.java ฉันจะเห็น:

public MyElement createMyElement() {
    return new MyElement();
}

แล้วตกลงคืออะไร? ทำไมฉันถึงต้องกังวลกับการรักษาคลาส ObjectFactory ไว้ด้วย? ฉันคิดว่ามันจะถูกเขียนทับด้วยถ้าฉันจะคอมไพล์ใหม่จากสคีมาที่เปลี่ยนแปลง


ฉันไม่แน่ใจว่าเป็นการออกแบบที่ตั้งใจไว้หรือเปล่า แต่ฉันพบว่า ObjectFactory เป็นคลาสที่เหมาะสำหรับการสร้าง JAXBContext คุณต้องแจกแจงบางชั้นเรียนที่นั่นและ JAXB จะทำตามวิธีการของพวกเขา ฯลฯ ดังนั้นพวกเขาจึงเป็นเหมือนราก และ ObjectFactory มีการอ้างอิงถึงองค์ประกอบทั้งหมดดังนั้นจึงเพียงพอที่จะใช้ ObjectFactory.class เพื่อสร้าง JAXBContext กับคลาสที่เกี่ยวข้องทั้งหมด
vbezhenar

คำตอบ:


68

ความเข้ากันได้ย้อนหลังไม่ใช่เหตุผลเดียว :- ป

ด้วยสคีมาที่ซับซ้อนมากขึ้นเช่นโครงสร้างที่มีข้อ จำกัด ที่ซับซ้อนเกี่ยวกับค่าที่เนื้อหาขององค์ประกอบสามารถรับได้บางครั้งคุณต้องสร้างJAXBElementวัตถุจริง โดยปกติแล้วพวกเขาไม่ได้เป็นเรื่องเล็กน้อยที่จะสร้างด้วยมือดังนั้นcreate*วิธีการนี้จึงเป็นเรื่องยากสำหรับคุณ ตัวอย่าง (จากสคีมา XHTML 1.1):

@XmlElementDecl(namespace = "http://www.w3.org/1999/xhtml", name = "style", scope = XhtmlHeadType.class)
public JAXBElement<XhtmlStyleType> createXhtmlHeadTypeStyle(XhtmlStyleType value) {
    return new JAXBElement<XhtmlStyleType>(_XhtmlHeadTypeStyle_QNAME, XhtmlStyleType.class, XhtmlHeadType.class, value);
}

นี่คือวิธีรับ<style>แท็กลงใน<head>แท็ก:

ObjectFactory factory = new ObjectFactory();
XhtmlHtmlType html = factory.createXhtmlHtmlType();
XhtmlHeadType head = factory.createXhtmlHeadType();
html.setHead(head);
XhtmlStyleType style = factory.createXhtmlStyleType();
head.getContent().add(factory.createXhtmlHeadTypeStyle(style));

การใช้สามครั้งแรกObjectFactoryอาจถือได้ว่าไม่จำเป็น (แม้ว่าจะมีประโยชน์สำหรับความสม่ำเสมอ) แต่การใช้งานครั้งที่สี่ทำให้ JAXB ใช้งานง่ายกว่ามาก การถ่ายภาพต้องเขียนnew JAXBElementด้วยมือทุกครั้ง!


คุณสามารถยกตัวอย่าง / การอ้างอิงว่าองค์ประกอบ Schema จำเป็นต้องมีอะไร (หรือซับซ้อนเพียงใด) เพื่อให้สร้าง * () ทำสิ่งที่มีประโยชน์ได้หรือไม่? ฉันมีปัญหาในการค้นหาส่วนของสคีมาที่คุณอ้างอิงกับตัวอย่าง JAXB ของคุณ ถ้าสคีมาของฉันซับซ้อนขึ้นในภายหลังก็คงจะดีสำหรับการสร้าง * เพื่อจัดการบางส่วนสำหรับฉัน แต่เนื่องจากมันถูกสร้าง * จึงไม่ต้องกังวลกับการสร้างองค์ประกอบย่อยด้วยตัวมันเอง ..
Andrew Coleson

หากคุณดาวน์โหลดทาร์บอล XHTML 1.1 และ XHTML Modularization 1.1 คุณจะพบไดเร็กทอรีที่เรียกว่า "SCHEMA" ใส่ไฟล์. xsd ทั้งหมดในไดเร็กทอรีเดียวกัน ไฟล์. xsd บางไฟล์จะนำเข้าw3.org/2001/xml.xsdด้วย คุณจะต้องปรับตำแหน่งให้เหมาะสมหากคุณไม่ต้องการให้ดาวน์โหลดไฟล์ทุกครั้งที่คุณเรียกใช้ xjc [ต่อ]
Chris Jester-Young

[ต่อ] ส่วนเฉพาะของ. xsd ที่ระบุเนื้อหาของ <head> คือในกรณีนี้ใน xhtml11-model-1.xsd ภายใต้กลุ่ม xhtml.head.content
Chris Jester-Young

2
ไม่ว่าในกรณีใดไม่มีใครชี้ปืนไปที่หัวของคุณโดยบอกว่าคุณต้องใช้ ObjectFactory (แม้ว่าฉันจะพบว่ามันสะดวกในการใช้งานก็ตาม) แต่เมื่อคุณเจอกรณีที่มันมีประโยชน์อย่างแท้จริงคุณจะรู้ :-)
Chris Jester-Young

ขอบคุณ! ฉันเดาว่าสคีมาของฉันไม่ซับซ้อนเพียงพอ แต่ฉันจะเก็บไว้ในอนาคต :) ฉันรู้ว่าฉันต้องขาดอะไรไป
Andrew Coleson

40

ดังที่ @Chris ชี้ให้เห็นบางครั้ง JAXB ไม่สามารถทำงานกับ POJO ได้เนื่องจากไม่สามารถแมปสคีมากับ Java ได้ทุกประการ ในกรณีเหล่านี้อJAXBElementอบเจ็กต์ Wrapper จำเป็นต้องให้ข้อมูลประเภทเพิ่มเติม

มีสองตัวอย่างที่เป็นรูปธรรมที่ฉันเจอซึ่งเป็นเรื่องธรรมดา

  • หากคุณต้องการรวมอ็อบเจ็กต์ของคลาสที่ไม่มี@XmlRootElementคำอธิบายประกอบ โดยค่าเริ่มต้น XJC จะสร้างขึ้น@XmlRootElementสำหรับองค์ประกอบบางอย่างเท่านั้นไม่ใช่สำหรับองค์ประกอบอื่น ๆ ตรรกะที่แน่นอนสำหรับสิ่งนี้ค่อนข้างซับซ้อน แต่คุณสามารถบังคับให้ XJC สร้าง@XmlRootElementคลาสเพิ่มเติมโดยใช้"โหมดการผูกแบบง่าย"

  • เมื่อสคีมาของคุณใช้กลุ่มการทดแทน นี่เป็นการใช้งานสคีมาขั้นสูง แต่ XJC แปลกลุ่มการทดแทนเป็น Java โดยใช้JAXBElementเครื่องห่อหุ้มจำนวนมาก

ดังนั้นในโมเดลอ็อบเจ็กต์ที่สร้างโดย XJC ซึ่งใช้ประโยชน์อย่างมากJAXBElement(ไม่ว่าด้วยเหตุผลใดก็ตาม) คุณต้องมีวิธีสร้างJAXBElementอินสแตนซ์เหล่านั้น การสร้างขึ้นObjectFactoryเป็นวิธีที่ง่ายที่สุดในการทำ คุณสามารถสร้างได้ด้วยตัวเอง แต่มันยุ่งเหยิงและเกิดข้อผิดพลาดได้ง่าย


ขอบคุณสำหรับตัวอย่างเพิ่มเติม!
Andrew Coleson

2
ว้าวเป็นคำตอบที่ชนะ +1
Chris Jester-Young

ฉันต้องการใช้ annox เพื่อสร้าง XmlRootElement เป็น 95% ของเวลาถ้าฉันมี elememtn ที่อ้างถึง complexType ฉันต้องการ XmlRootElement (เช่นกัน 100% เนื่องจากฉันยังไม่ได้ใช้กรณีการใช้งานที่ฉันไม่ต้องการสิ่งนั้น ยัง)
Dean Hiller

9

ความเข้ากันได้ย้อนหลังฉันเดาว่า ...

http://weblogs.java.net/blog/kohsuke/archive/2005/08/a_story_of_migr.html :

... ไม่มี ObjectFactory.createXYZ อีกต่อไป ปัญหาเกี่ยวกับวิธีการโรงงานเหล่านั้นคือพวกเขาโยน JAXBException ที่ตรวจสอบแล้ว ตอนนี้คุณสามารถทำ XYZ () ใหม่ได้โดยไม่ต้องลอง / จับบล็อกอีกต่อไป (ฉันรู้ฉันรู้ ... นี่คือหนึ่งในสิ่งที่ "เราคิด!?") ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.