这个程序:
import foo.bar.baz.ClassSpecificallyIncluded;
import javax.xml.bind.JAXBContext;
public class A {
public static void main(String[] args) throws Exception {
System.out.println(JAXBContext.newInstance(ClassSpecificallyIncluded.class).toString());
System.out.println(JAXBContext.newInstance("foo.bar.baz").toString());
}
}
为第一个和第二个JAXBContext生成不同的输出:
jar:file:/ C:/dev/trunk/rt/tomcat/shared/lib/webservices-rt-2.0.1.jar!/com/sun/xml/bind/v2/runtime/JAXBContextImpl.class Build -Id:1.0
本文所知的类:
[B
布尔
字节
焦炭
foo.bar.baz.Class1
foo.bar.baz.Class1 $ NestedClass
foo.bar.baz.Class2
foo.bar.baz.ClassSpecificallyIncluded
foo.bar.baz.AnotherClass
com.sun.xml.bind.api.CompositeStructure
双
浮
INT
java.awt.Image中
java.io.File的
java.lang.Boolean的
java.lang.Byte的
java.lang.Character中
java.lang.Class中
java.lang.Double中
java.lang.Float中
java.lang.Integer中
java.lang.Long中
java.lang.Object继承
java.lang.Short的
java.lang.String中
java.lang.Void的
java.math.BigDecimal的
java.math.BigInteger的
java.net.URI中的
的java.net.URL
java.util.Calendar中
java.util.Date
java.util.GregorianCalendar中
java.util.UUID中
的javax.activation.DataHandler
javax.xml.bind.JAXBElement
javax.xml.datatype.Duration中
javax.xml.datatype.XMLGregorianCalendar中
javax.xml.namespace.QName中
javax.xml.transform.Source
长
短
无效jar:file:/ C:/dev/trunk/rt/tomcat/shared/lib/webservices-rt-2.0.1.jar!/com/sun/xml/bind/v2/runtime/JAXBContextImpl.class Build -Id:1.0
本文所知的类:
[B
布尔
字节
焦炭
foo.bar.baz.Class1
foo.bar.baz.Class1 $ NestedClass
foo.bar.baz.Class2
的<<< CLASS IS MISSING HERE>>>
foo.bar.baz.AnotherClass
com.sun.xml.bind.api.CompositeStructure
双
浮
INT
java.awt.Image中
java.io.File的
java.lang.Boolean的
java.lang.Byte的
java.lang.Character中
java.lang.Class中
java.lang.Double中
java.lang.Float中
java.lang.Integer中
java.lang.Long中
java.lang.Object继承
java.lang.Short的
java.lang.String中
java.lang.Void的
java.math.BigDecimal的
java.math.BigInteger的
java.net.URI中的
的java.net.URL
java.util.Calendar中
java.util.Date
java.util.GregorianCalendar中
java.util.UUID中
的javax.activation.DataHandler
javax.xml.bind.JAXBElement
javax.xml.datatype.Duration中
javax.xml.datatype.XMLGregorianCalendar中
javax.xml.namespace.QName中
javax.xml.transform.Source
长
短
无效
然而,ClassSpecificallyIncluded位于foo.bar.baz包中:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.05.14 at 10:47:17 PM IST
//
package foo.bar.baz;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"applicationArea",
"dataArea"
})
@XmlRootElement(name = "ClassSpecificallyIncluded")
public class ClassSpecificallyIncluded {...
两个JAXBContexts的类路径和类加载器都是相同的。
那么为什么第二个JAXBContext不知道ClassSpecificallyIncluded?
答案 0 :(得分:3)
您的问题的答案在这里得到了有效的回答:
Can you find all classes in a package using reflection?
<强>答案:强> 没有设计,java不知道,也找不到包中的每个类。 Java建立在“及时”的概念之上。对于这个目的而言,这意味着java在得到特定内容之前不知道它是什么。
所以从这个角度来看,JAXB无法找到包中的类。
如果每次需要上下文时都必须准确地告知每个班级,那将是不方便的。因此,作为一种便捷方法,JAXB为您提供了提供包名称的选项。
为了克服java的限制,它尝试从该包加载ObjectFactory
和jaxb.index
文件。它可以这样做,因为它们是特定的名称。如果找到一个,那么它将它们用作包的清单。如果两者都找不到,它就没有选择,只能中止,因为它不可能知道包中的内容。
答案 1 :(得分:1)
假设我在名为forum20273355
的目录中有以下类:
如果我使用以下代码创建JAXBContext
:
JAXBContext jc = JAXBContext.newInstance("forum20273355");
然后我会得到以下异常:
Exception in thread "main" javax.xml.bind.JAXBException: Provider com.sun.xml.bind.v2.ContextFactory could not be instantiated: javax.xml.bind.JAXBException: "forum20273355" doesnt contain ObjectFactory.class or jaxb.index
- with linked exception:
[javax.xml.bind.JAXBException: "forum20273355" doesnt contain ObjectFactory.class or jaxb.index]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:146)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:334)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:431)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:394)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:298)
at forum20273355.Demo.main(Demo.java:8)
Caused by: javax.xml.bind.JAXBException: "forum20273355" doesnt contain ObjectFactory.class or jaxb.index
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:172)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:132)
... 5 more
jaxb.index
或ObjectFactory
下面我们将创建一个jaxb.index
文件和ObjectFactory
,这将导致Person
类被处理以查看会发生什么。
<强> jaxb.index 强>
jaxb.index
是一个文本文件,其中包含一个回车分隔的短类名列表。
Person
<强>的ObjectFactory 强>
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public Person createPerson() {
return new Person();
}
}
已处理的课程
显然已处理Person
,但超类Mammal
和引用类Address
也是如此。未处理的类是子类Customer
。
forum20273355.Address
forum20273355.Mammal
forum20273355.Person
显然,我们可以将子类Customer
添加到jaxb.index
或ObjectFactory
。我们还可以利用@XmlSeeAlso
注释来实现这一目标。
package forum20273355;
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({Customer.class})
public class Person extends Mammal {
现在也处理Customer
。
forum20273355.Address
forum20273355.Customer
forum20273355.Mammal
forum20273355.Person
您在评论中写的所有内容都是真实的。缺少的是需要jaxb.index
文件或ObjectFactory
类来完成该过程。从XML模式生成模型时,会生成ObjectFactory
,其中包含引导模型的所有必要引用。当你从Java类开始时,我建议从Java类而不是包名引导,但是适用相同的规则。
但Sun Oracle文档说:JAXBContext.newInstance( “com.acme.foo:com.acme.bar”)初始化JAXBContext实例 从冒号分隔的Java包名称列表中。
是的,包名称指定了要查找元数据的位置。
每个java包都包含JAXB映射类,模式派生类 和/或用户注释的类。
真。
此外,java包可能包含JAXB包注释 必须处理。 (参见JLS第3版,第7.4.1节。包 注解)。
是的,肯定会应用包注释。