JAXB 2'nin ObjectFactory sınıflarının amacı nedir?


98

JAXB'yi kullanma konusunda yeniyim ve XML Şemamdan bir sınıf kümesi oluşturmak için JAXB 2.1.3'ün xjc'sini kullandım. Şemamdaki her eleman için bir sınıf oluşturmanın yanı sıra, bir ObjectFactory sınıfı yarattı.

Öğeleri doğrudan somutlaştırmamı engelleyen hiçbir şey yok gibi görünüyor

MyElement element = new MyElement();

oysa öğreticiler tercih ediyor

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

ObjectFactory.java'ya bakarsam şunu görüyorum:

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

öyleyse anlaşma nedir? Neden ObjectFactory sınıfını etrafta tutmakla uğraşayım? Değiştirilmiş bir şemadan yeniden derlemek istersem, onun da üzerine yazılacağını varsayıyorum.


Amaçlanan tasarım olup olmadığından emin değilim, ancak ObjectFactory'yi JAXBContext oluşturma için ideal bir sınıf buldum. Orada bazı sınıfları numaralandırmanız gerekir ve JAXB yöntemlerini vb. Takip eder, böylece kökler gibi bir şey olurlar. Ve ObjectFactory'nin tüm öğelere referansları vardır, bu nedenle JAXBContext'i tüm ilgili sınıflarla oluşturmak için yalnızca ObjectFactory.class'ı kullanmak yeterlidir.
vbezhenar

Yanıtlar:


68

Geriye dönük uyumluluk tek neden değil. :-P

Bir öğenin içeriğinin alabileceği değerler üzerinde karmaşık kısıtlamalara sahip olanlar gibi daha karmaşık şemalarda, bazen gerçek JAXBElementnesneler oluşturmanız gerekir . Genellikle elle oluşturmak önemsiz değildir, bu nedenle create*yöntemler sizin için çok çalışır. Örnek (XHTML 1.1 şemasından):

@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>Etiketi bir etikete şu şekilde alırsınız <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));

İlk üç kullanımın ObjectFactorygereksiz olduğu düşünülebilir (tutarlılık için yararlı olsa da), ancak dördüncüsü JAXB'nin kullanımını çok daha kolay hale getirir. new JAXBElementHer seferinde elle yazmak zorunda görüntüleme !


Yarat * () 'ın yararlı bir şey yapması için bir Şema öğesinin ne (veya ne kadar karmaşık) olması gerektiğine dair bir örnek / referans verebilir misiniz? JAXB örneğinizle başvurduğunuz Şema parçasını bulmakta sorun yaşıyorum. Şemam daha sonra daha karmaşık hale gelirse, oluşturmak * için onun bir kısmını benim için halletmek kesinlikle iyi olurdu, ancak oluşturulduğu için * kendi başına alt öğeler oluşturmaya bile zahmet etmiyor ..
Andrew Coleson

XHTML 1.1 ve XHTML Modularization 1.1 tarball'larını indirirseniz, "SCHEMA" adlı dizinler bulacaksınız. Tüm .xsd dosyalarını aynı dizinlere koyun. .Xsd dosyalarından bazıları w3.org/2001/xml.xsd'yi de içe aktaracaktır ; xjc'yi her çalıştırdığınızda dosyanın indirilmesini istemiyorsanız, konumları uygun şekilde ayarlamak isteyeceksiniz. [devam]
Chris Jester-Young

[devamı] .xsd'nin bir <head> içeriğini belirten belirli kısmı, bu durumda, xhtml11-model-1.xsd'de, xhtml.head.content grubunun altında bulunur.
Chris Jester-Young

2
Her halükarda, kimse kafanıza silah doğrultup ObjectFactory kullanmanız gerektiğini söylemiyor (her ne kadar ben onu kullanmak için kullanışlı bulsam da), ancak gerçekten kullanışlı olduğu bir durumla karşılaştığınızda, bunu anlayacaksınız. :-)
Chris Jester-Young

Teşekkürler! Sanırım şemam yeterince karmaşık değil, ama gelecek için aklımda tutacağım. :) Bir şeyleri kaçırmam gerektiğini biliyordum.
Andrew Coleson

40

@Chris'in belirttiği gibi, bazen JAXB POJO'larla çalışamaz, çünkü şema tam olarak Java'ya eşlenemez. Bu durumlarda, JAXBElementek tip bilgilerini sağlamak için sarmalayıcı nesneler gereklidir.

Bunun yaygın olduğu yerde karşılaştığım iki somut örnek var.

  • @XmlRootElementEk açıklamaya sahip olmayan bir sınıfın nesnesini sıralamak istiyorsanız . Varsayılan olarak XJC yalnızca @XmlRootElementbazı öğeler için üretir , diğerleri için değil. Bunun tam mantığı biraz karmaşıktır, ancak XJC'yi "basit bağlama modunu"@XmlRootElement kullanarak daha fazla sınıf oluşturmaya zorlayabilirsiniz.

  • Şemanız ikame grupları kullandığında. Bu oldukça gelişmiş şema kullanımıdır, ancak XJC, JAXBElementsarmalayıcıları yoğun bir şekilde kullanarak ikame gruplarını Java'ya çevirir .

Bu yüzden JAXBElement(her ne sebeple olursa olsun) yoğun şekilde kullanılan XJC tarafından üretilmiş bir nesne modelinde , bu JAXBElementörnekleri oluşturmanın bir yoluna ihtiyacınız var . Oluşturulan ObjectFactory, bunu yapmanın açık ara en kolay yoludur. Sen edebilirsiniz kendiniz inşa, ama aksak ve hataya açık bunu bu.


Ek örnekler için teşekkürler!
Andrew Coleson

2
Vay canına, bu kazanan bir cevap. +1
Chris Jester-Young

Bir complexType'a atıfta bulunan bir elememtn'e sahipsem XmlRootElement'i% 95 oranında oluşturmak için annox kullanmayı seviyorum, XmlRootElement'i istiyorum (daha çok% 100 gibi, çünkü bunu istemediğim kullanım senaryosuna ulaşmadım) henüz)
Dean Hiller

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.