JAXB学习 (四)JAXBContext

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

 

 

 

JAXBContext类提供的功能主要有:

 

  • marshall
  • unmarshall
  • validate

 

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

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()方法

    ContextFinder.find(  
                            /* The default property name according to the JAXB spec */  
                            JAXB_CONTEXT_FACTORY,  
      
                            /* the context path supplied by the client app */  
                            contextPath,  
      
                            /* class loader to be used */  
                            classLoader,  
                            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代码 
    javax.xml.bind.context.factory=com.liulutu.student.model.CustomJAXBContextFactory  
     

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

    package com.liulutu.student.model;  
      
    import javax.xml.bind.JAXBContext;  
      
    public class CustomJAXBContextFactory{  
      
    }  
     

 

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

 

JAXBContext jaxbContext = JAXBContext.newInstance("com.liulutu.student.model");  
  
ObjectFactory factory = new ObjectFactory();  
Students students = factory.createStudents();  
addNewStudentTo(factory, students, "a", SexType.MALE);  
addNewStudentTo(factory, students, "b", SexType.FEMALE);  
Marshaller marshaller = jaxbContext.createMarshaller();  
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  
marshaller.setSchema(SchemaFactory.newInstance(  
        XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(  
        new File("students.xsd")));  
marshaller.marshal(students, new File("a.xml")); 

 

 然后检查一下运行结果:

 

    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)    
     - with linked exception:  
    [java.lang.NoSuchMethodException: com.liulutu.student.model.CustomJAXBContextFactory.createContext(java.lang.String, java.lang.ClassLoader)]  
        at javax.xml.bind.ContextFinder.newInstance(Unknown Source)  
        at javax.xml.bind.ContextFinder.find(Unknown Source)  
        at javax.xml.bind.JAXBContext.newInstance(Unknown Source)  
        at javax.xml.bind.JAXBContext.newInstance(Unknown Source)  
        at javax.xml.bind.JAXBContext.newInstance(Unknown Source)  
        at com.liulutu.student.test.TestMarshaller.main(TestMarshaller.java:22)  
    Caused by: java.lang.NoSuchMethodException: com.liulutu.student.model.CustomJAXBContextFactory.createContext(java.lang.String, java.lang.ClassLoader)  
        at java.lang.Class.getMethod(Unknown Source)  
        ... 6 more  
     

 

 

你可能感兴趣的:(java,JAXB,JAXBContext)