JAXB 2의 ObjectFactory 클래스의 요점은 무엇입니까?


98

저는 JAXB를 처음 사용하고 JAXB 2.1.3의 xjc를 사용하여 XML 스키마에서 클래스 집합을 생성했습니다. 내 스키마의 각 요소에 대한 클래스를 생성하는 것 외에도 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매번 손 으로 써야하는 영상 !


create * ()가 유용한 작업을 수행하기 위해 필요한 스키마 요소 (또는 얼마나 복잡한 지)에 대한 예제 / 참조를 제공 할 수 있습니까? JAXB 예제에서 참조하는 스키마의 일부를 찾는 데 문제가 있습니다. 나중에 내 스키마가 더 복잡해지면 create *가 저를 위해 일부를 처리하는 것이 좋겠지 만 create *가 자체적으로 하위 요소를 생성하는 것을 귀찮게하지 않습니다.
Andrew Coleson

XHTML 1.1 및 XHTML Modularization 1.1 tarball을 다운로드하면 "SCHEMA"라는 디렉토리를 찾을 수 있습니다. 모든 .xsd 파일을 동일한 디렉토리에 넣으십시오. 일부 .xsd 파일은 w3.org/2001/xml.xsd 도 가져 옵니다 . xjc를 실행할 때마다 파일을 다운로드하지 않으려면 위치를 적절하게 조정해야합니다. [계속]
Chris Jester-Young

[cont] <head>의 내용을 지정하는 .xsd의 특정 부분은이 경우 xhtml.head.content 그룹 아래의 xhtml11-model-1.xsd입니다.
Chris Jester-Young

2
어쨌든 ObjectFactory를 사용해야한다고 말하는 사람은 아무도 없지만 (사용하기 편리하다고 생각하지만) 진정으로 유용한 경우를 발견하면 알게 될 것입니다. :-)
Chris Jester-Young

감사! 내 스키마가 충분히 복잡하지 않은 것 같지만 미래를 위해 염두에 두겠습니다. :) 나는 내가 뭔가를 놓쳐 야한다는 것을 알고 있었다.
Andrew Coleson 2009-06-06

39

@Chris가 지적했듯이 스키마가 Java에 정확히 매핑 될 수 없기 때문에 JAXB가 POJO와 함께 작동하지 않는 경우가 있습니다. 이러한 경우 JAXBElement추가 유형 정보를 제공하려면 래퍼 개체가 필요합니다.

이것이 흔한 곳에서 내가 본 두 가지 구체적인 예가 있습니다.

  • @XmlRootElement주석 이없는 클래스의 객체를 마샬링하려는 경우 . 기본적으로 XJC @XmlRootElement는 일부 요소에 대해서만 생성 하고 다른 요소에 대해서는 생성 하지 않습니다. 이에 대한 정확한 논리는 약간 복잡하지만 "단순 바인딩 모드"를@XmlRootElement 사용하여 XJC가 더 많은 클래스 를 생성하도록 강제 할 수 있습니다.

  • 스키마가 대체 그룹을 사용하는 경우. 이것은 꽤 고급 스키마 사용이지만 XJC는 JAXBElement랩퍼 를 많이 사용하여 대체 그룹을 Java로 변환 합니다.

따라서 JAXBElement(어떤 이유로 든) 많이 사용하는 XJC 생성 개체 모델에서 이러한 JAXBElement인스턴스 를 구성하는 방법이 필요 합니다. 생성 된 ObjectFactory것이 가장 쉬운 방법입니다. 당신은 할 수 있습니다 그들에게 자신을 구성,하지만 어설픈 오류가 발생하기 쉬운 그렇게 할 수 있습니다.


추가 예제에 감사드립니다!
Andrew Coleson

2
와, 그게 좋은 대답입니다. +1
Chris Jester-Young

나는 complexType을 참조하는 elememtn이 있으면 annox를 사용하여 95 %의 시간으로 XmlRootElement를 생성하고 싶습니다. XmlRootElement를 원합니다. 아직)
Dean Hiller

9

이전 버전과의 호환성, 나는 추측한다 ...

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

... 더 이상 ObjectFactory.createXYZ가 없습니다. 이러한 팩토리 메소드의 문제점은 확인 된 JAXBException을 던진다는 것입니다. 이제 더 이상 try / catch 블록이 아닌 new XYZ ()를 수행 할 수 있습니다. (알아요, 알아요 ... 이건 "우리가 무슨 생각을하고 있었나요!?"라는 것 중 하나입니다) ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.