`
zzc1684
  • 浏览: 1199619 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

JAXB学习四 (理解JAXBContext)

    博客分类:
  • JAXB
阅读更多

在jaxb应用中,JAXBContext类可以说是使用JAXB API的入口点,就像是一道门,只有通过它才能进入到jaxb的世界里。

 

JAXBContext类提供的功能主要有:

  • marshall
  • unmarshall
  • validate

在jaxb中,通常如果声明JAXBContext对象:

Java代码 复制代码 收藏代码
  1. JAXBContext jaxbContext = JAXBContext.newInstance("com.liulutu.student.model");  

不过如果稍稍研究一下 JAXBContext 类,就会发现,其实它是一个抽象类, 但是从源码里却不能很清楚的看到到底是哪个实现类被具体的用到。

 

那么在 JAXBContext.newInstance("com.liulutu.student.model") 的背后肯定有一些猫腻。下面就简单介绍一下这背后所隐藏的秘密。

 

一、代码追踪

 首先看一下JAXBContext.newInstance("com.liulutu.student.model") 它的调用关系图:

可以看到,它一直调到了javax.xml.bind.ContextFinder类的find()方法:

Java代码 复制代码 收藏代码
  1. ContextFinder.find(   
  2.                         /* The default property name according to the JAXB spec */  
  3.                         JAXB_CONTEXT_FACTORY,   
  4.   
  5.                         /* the context path supplied by the client app */  
  6.                         contextPath,   
  7.   
  8.                         /* class loader to be used */  
  9.                         classLoader,   
  10.                         properties );   

其中这里的 contextPath 就是传入的包名,如上的 com.liulutu.student.model ; JAXB_CONTEXT_FACTORY 是一个预定义的值 javax.xml.bind.context.factory 。

 

KEY: 在ContextFinder的find方法里,它首先会去找一个东西:jaxb.properties 。它会试图在你传入的包中去查找有没有一个名为 jaxb.properties 的properties文件;如果有,则会继续深入,看看有没有key值为传入的 factoryId ,在这里也就是值为 JAXB_CONTEXT_FACTORY 的key值,如果有,则把它对应的 value 认为是需要的 JAXBContext的factory的实现,会自动调它的 createContext 文件。

 

OTHER: 否则就会去查找 系统属性;再查找类路径上的META-INF/services/目录;最后再不行就反正一个默认的实现 /jaxb/src/com/sun/xml/internal/bind/v2/ContextFactory.java 。不过这些事情我不再关心了。

 

回过头看KEY部分。由此我们可以想到,如果要指定自定义的JAXBContext的实现,只需要在包下提供一个jaxb.properties文件;文件里有一条key为 javax.xml.bind.context.factory , 值指定一个包含有 createContext()方法 并且该方法的返回值是一个JAXBContext 对象的类。

 

二、实践

可以简单实践一下,例如我在包 com.liulutu.student.model 下新建一个文件 jaxb.properties,内容如下:

 

Java代码 复制代码 收藏代码
  1. javax.xml.bind.context.factory=com.liulutu.student.model.CustomJAXBContextFactory  

 然后,在CustomJAXBContextFactory类里什么也不实现:

Java代码 复制代码 收藏代码
  1. package com.liulutu.student.model;   
  2.   
  3. import javax.xml.bind.JAXBContext;   
  4.   
  5. public class CustomJAXBContextFactory{   
  6.   
  7. }   

然后再测试一下marshall或unmarshall的代码,例如:

Java代码 复制代码 收藏代码
  1. JAXBContext jaxbContext = JAXBContext.newInstance("com.liulutu.student.model");   
  2.   
  3. ObjectFactory factory = new ObjectFactory();   
  4. Students students = factory.createStudents();   
  5. addNewStudentTo(factory, students, "a", SexType.MALE);   
  6. addNewStudentTo(factory, students, "b", SexType.FEMALE);   
  7. Marshaller marshaller = jaxbContext.createMarshaller();   
  8. marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);   
  9. marshaller.setSchema(SchemaFactory.newInstance(   
  10.         XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(   
  11.         new File("students.xsd")));   
  12. marshaller.marshal(students, new File("a.xml"));   

然后检查一下运行结果:

 

Java代码 复制代码 收藏代码
  1. Exception in thread "main" javax.xml.bind.JAXBException: Provider com.liulutu.student.model.CustomJAXBContextFactory could not be instantiated: java.lang.NoSuchMethodException: com.liulutu.student.model.CustomJAXBContextFactory.createContext(java.lang.String, java.lang.ClassLoader)     
  2.  - with linked exception:   
  3. [java.lang.NoSuchMethodException: com.liulutu.student.model.CustomJAXBContextFactory.createContext(java.lang.String, java.lang.ClassLoader)]   
  4.     at javax.xml.bind.ContextFinder.newInstance(Unknown Source)   
  5.     at javax.xml.bind.ContextFinder.find(Unknown Source)   
  6.     at javax.xml.bind.JAXBContext.newInstance(Unknown Source)   
  7.     at javax.xml.bind.JAXBContext.newInstance(Unknown Source)   
  8.     at javax.xml.bind.JAXBContext.newInstance(Unknown Source)   
  9.     at com.liulutu.student.test.TestMarshaller.main(TestMarshaller.java:22)   
  10. Caused by: java.lang.NoSuchMethodException: com.liulutu.student.model.CustomJAXBContextFactory.createContext(java.lang.String, java.lang.ClassLoader)   
  11.     at java.lang.Class.getMethod(Unknown Source)   
  12.     ... 6 more  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics