`
234390216
  • 浏览: 10239191 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:462915
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1776036
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1398781
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:395164
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:680181
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:531175
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1185088
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:468873
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:151505
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:68359
社区版块
存档分类
最新评论

JAXB(三)——JAXBContext及其优化

    博客分类:
  • JAXB
阅读更多

JAXBContext介绍及性能优化

摘要 本文主要介绍基于package创建JAXBContext,以及阐述JAXBContext存在的性能问题及其优化。

JAXBContext介绍

JAXBContext是我们在使用JAXB时的入口类,我们需要通过它的实例来建立XML和Java类之间的映射关系,需要通过它来创建用于转换Java对象到XML的Marshaller或是创建用于转换XML到Java对象的Unmarshaller。JAXBContext的实例需要通过JAXBContext.newInstance(..)方法产生,JAXBContext中定义了重载的5个newInstance(..)方法,定义如下:

public static JAXBContext newInstance( String contextPath );
public static JAXBContext newInstance( String contextPath, ClassLoader classLoader );
public static JAXBContext newInstance( String contextPath, ClassLoader classLoader, Map<String,?>  properties  );
public static JAXBContext newInstance( Class... classesToBeBound );
public static JAXBContext newInstance( Class[] classesToBeBound, Map<String,?> properties );

上述5个方法的区别在于是基于package的还是基于class的。contextPath用于指定需要绑定XML的Java类所在的包定义;classLoader用于指定使用的类加载器,未指定时将使用当前线程上下文所绑定的类加载器;properties用于指定JAXB实现者特定的属性;classesToBeBound用于直接指定需要绑定的Java类。

之前介绍的都是通过直接指定相关的Class作为入参的形式创建JAXBContext,如下所示:

JAXBContext jaxbContext = JAXBContext.newInstance(Response.class, Person.class);

这里着重介绍一下基于package创建JAXBContext的示例,如下所示:

JAXBContext jaxbContext = JAXBContext.newInstance("com.xxx.jaxb");

但是这时候并不是指定的包中所有的Class都会用来创建JAXBContext。按照JAXB的规范,我们需要在对应的包中创建一个jaxb.index文件,然后在其中指定创建JAXBContext时需要用到的Class,每个Class名称占一行,只需要写Class名称即可,如我们在创建JAXBContext时需要用到Response和Person类,我们就可以中jaxb.index文件中如下定义:

Response
Person

然后后续就可以用对应的JAXBContext来进行相应的Marshal和UnMarshal操作了。通过指定包名称创建JAXBContext的方式可以把程序中各种可能的场景中需要使用到的Class都初始化到一个JAXBContext中,这样可以保证这个JAXBContext可以在各种可能的场景下都能满足需求,JAXBContext的初始化是非常耗CPU的,重用JAXBContext有助于提升性能。另一方面我们如果在某一时刻调整使用的Class时可以不用修改源码,直接修改jaxb.index文件中定义的Class即可,这可比修改源码要简单的多。

为了保证文章的完整性,以下给出一个基于包名称初始化JAXBContext的完整示例。

@Test
public void testPerson() throws Exception {
    Person person = new Person();
    person.setId(1);
    person.setName("张三");
    Response response = this.newResponse(person);
    JAXBContext jaxbContext = JAXBContext.newInstance("com.xxx.jaxb");
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(response, System.out);
}

private Response newResponse(Data realData) {
    Response response = new Response();
    response.setReturnCode(100);
    response.setMessage("AAAA");
    ResultData resultData = new ResultData();
    resultData.setRealData(realData);
    response.setResultData(resultData);
    return response;
}
@XmlRootElement
public class Response {

    private int returnCode;
    private String message;
    @XmlElement(name = "data")
    private ResultData resultData;

    //省略get/set

}
public class ResultData {
    @XmlElementRef
    private Data realData;

    //省略get/set
}
public class Data {

}
@XmlRootElement(name="dept")
public class Person extends Data {
    @XmlAttribute
    private Integer id;
    private String name;

    //省略get/set
}
Response
Person

生成的XML如下:

<response>
    <returnCode>100</returnCode>
    <message>AAAA</message>
    <data>
        <dept id="1">
            <name>张三</name>
        </dept>
    </data>
</response>

使用直接指定class创建JAXBContext的方式我们的代码可以是如下这样:

@Test
public void testPerson2() throws Exception {
    Person person = new Person();
    person.setId(1);
    person.setName("张三");
    Response response = this.newResponse(person);
    JAXBContext jaxbContext = JAXBContext.newInstance(Person.class, Response.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(response, System.out);
}

通过package创建JAXBContext时也允许创建指定多个package,多个package之间通过英文冒号分隔,如下我们在创建JAXBContext时就同时指定了com.xxx.jaxbcom.xxx.jaxb2两个package。

JAXBContext jaxbContext = JAXBContext.newInstance("com.xxx.jaxb:com.xxx.jaxb2");

性能优化

每次在创建JAXBContext实例时,JAXBContext内部都需要维护好Java类和XML之间的映射关系,这个操作是十分消耗性能的。幸运的是JAXBContext是线程安全的,可以共享。关于JAXBContext存在的性能问题笔者准备了如下测试代码:

@Test
public void testPerformance() throws Exception {
    for (int j=0; j<5; j++) {
        int times = 100000;
        long t1 = System.currentTimeMillis();
        for (int i=0; i<times; i++) {
            JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.marshal(new Root(), new StringWriter());
        }
        long t2 = System.currentTimeMillis();
        System.out.println("不共用JAXBContext耗时:" + (t2-t1) + "ms");
        
        long t3 = System.currentTimeMillis();
        JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
        for (int i=0; i<times; i++) {
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.marshal(new Root(), new StringWriter());
        }
        long t4 = System.currentTimeMillis();
        System.out.println("共用JAXBContext耗时:" + (t4-t3) + "ms");
    }
}

循环测试5次,每次分别在共享JAXBContext和不共享JAXBContext的情况下进行十万次marshal操作,由于这里我们不关心生成的XML,也避免输出到控制台或文件中的IO影响,这里每次都创建一个StringWriter,StringWriter是基于内存操作的。在笔者64位ubuntu17.10系统、处理器是Intel® Core™ i5-7500 CPU @ 3.40GHz × 4、8GB内存的台式机下运行结果如下所示:

不共用JAXBContext耗时:17735ms
共用JAXBContext耗时:240ms
不共用JAXBContext耗时:16003ms
共用JAXBContext耗时:272ms
不共用JAXBContext耗时:15614ms
共用JAXBContext耗时:223ms
不共用JAXBContext耗时:15313ms
共用JAXBContext耗时:215ms
不共用JAXBContext耗时:15241ms
共用JAXBContext耗时:235ms

从测试结果我们可以很明显的看到共享JAXBContext的情况下性能有很明显的提升。共享JAXB时如果我们的所有的应用场景需要使用到的Class比较少时我们可以简单的在创建JAXBContext对象时传递所有需哟使用到的Class,把它保存起来之后都可以一直这样在我们的应用中使用它了。但是如果Class的定义在进行XML转换为Java对象时有冲突就不能这么做了,比如你有一个Person1和Person2两个Person类,它们映射的XML节点都是person,那么在把XML节点person转换为Java对象时是转换为Person1还是Person2呢?有这种场景获取Class相对较多时建议创建一个JaxbUtil工具类,所有的JAXBContext对象都由该工具类产生,在该工具类内部实现JAXBContext的重用,以下是一个简单的示例。

private static Map<List<Class<?>>, JAXBContext> jaxbContextMap = new ConcurrentHashMap<>();

public static JAXBContext getJAXBContext(Class<?> ...classes) throws JAXBException {
    List<Class<?>> classList = new ArrayList<>(Arrays.asList(classes));
    if (!jaxbContextMap.containsKey(classList)) {
        JAXBContext jaxbContext = JAXBContext.newInstance(classes);
        jaxbContextMap.put(classList, jaxbContext);
        return jaxbContext;
    }
    return jaxbContextMap.get(classList);
}

需要注意的是虽然JAXBContext是线程安全的,但是它由它产生的Marshaller和Unmarshaller对象是线程不安全的,切勿进行重用。

 

0
0
分享到:
评论

相关推荐

    JAXB乱码问题解决

    在Java开发中,JAXB(Java Architecture for XML Binding)是一个用于将XML文档和Java对象之间进行绑定的技术。在处理XML文件时,特别是涉及到序列化和反序列化时,可能会遇到字符编码问题,即所谓的“乱码”。这个...

    JAVA JAXB 解析XML嵌套子节点为字符串

    在Java开发中,JAXB(Java Architecture for XML Binding)是一个标准的API,用于将XML文档与Java对象之间进行互相转换。这个技术对于处理XML数据,尤其是解析和生成XML文档非常有用。当我们面临XML文档中存在嵌套子...

    JAXB 利用xsd文件生成java类

    JAXB (Java Architecture for XML Binding) 是Java平台上的一个标准,用于将XML文档与Java对象之间进行绑定,实现XML数据的解析和序列化。在Java开发中,JAXB提供了一种方便的方式,允许开发者通过XML Schema (XSD) ...

    JAXB技术实现xml与java对象互相转化代码教程

    使用java jdk的JAXB技术实现xml与java对象互相转化...•JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。 •Marshaller接口,将Java对象序列化为XML数据。 •Unmarshaller接口,将XML数据反序列化为Java对象。

    jaxb-impl-2.1.13.jar

    jaxb-impl-2.1.13.jar

    JaxbContext生成xml文件或java类对象转化注解

    JAXBContext 生成 XML 文件或 Java 类对象转换注解 JAXB(Java API for XML Binding)是一种将 Java 对象与 XML 进行转换的技术。JAXB 提供了一个快速便捷的方式将 Java 对象与 XML 进行转换。在 JAX-WS(Java 的 ...

    jaxb解析生成xml

    2. **性能**:由于JAXB是Java平台的标准部分,它通常比第三方库更快,因为它可以利用JVM的优化。 3. **自动类型检查**:在序列化和反序列化过程中,JAXB会自动执行类型检查,确保数据一致性。 4. **与XML Schema集成...

    android上使用 jaxb所需要的包

    1. `jaxb-api-2.2.7.jar`:这是JAXB的主要API,提供了基本的接口和类,如`javax.xml.bind.JAXBContext`和`javax.xml.bind.Marshaller`,用于实现XML和Java对象的转换。`JAXBContext`是整个转换过程的核心,负责创建...

    jaxb-api jaxb-impl jar

    它提供了必要的接口和类,如`javax.xml.bind.JAXBContext`, `Unmarshaller`, `Unmarshaller`, 和 `Validator`等,用于实现XML到Java对象的编组(marshalling)和反编组(unmarshalling)。API本身不包含具体的实现,...

    idea 中用jaxb 读xml中数据

    当我们需要处理XML文件,比如从XML中提取数据时,JAXB(Java Architecture for XML Binding)是一个强大的工具。本教程将详细解释如何在Idea中利用JAXB来读取XML文件中的数据。 JAXB是Java标准API,它提供了将Java...

    jaxb2.1jar包

    6. **性能优化**:JAXB2.1在性能方面进行了优化,提升了XML文档的解析速度和内存使用效率。 **二、JAXB API** `jaxb-api.jar` 包含了JAXB的主要API,其中包括核心的接口和类,如`javax.xml.bind.JAXBContext`,`...

    jaxb 使用实例

    2. **设置JAXB上下文**:使用`JAXBContext`来获取Java类型和XML之间的映射信息。这一步通常需要传递Java类的Class对象作为参数。 3. **序列化(Marshalling)**:创建`Marshaller`实例,并调用其`marshal()`方法将...

    jaxb2.3.0依赖jar.rar

    1. **Java SE 9+支持**:JAXB 2.3.0开始支持Java 9及其后续版本,这包括模块化系统(Jigsaw)的集成。 2. **API增强**:可能包含了新的API接口或方法,以提供更丰富的功能和更好的用户体验。 3. **性能优化**:可能...

    java学习之jaxb的学习一

    三、JAXB的基本使用 1. 定义Java类:首先,我们需要定义一个Java类,该类的属性对应XML文档中的元素和属性。JAXB会自动为这些属性生成getter和setter方法。 2. 创建JAXBContext:这是JAXB的核心,负责管理和控制XML...

    如何更好地jaxb使用

    如何更好地jaxb使用如何更好地jaxb使用如何更好地jaxb使用如何更好地jaxb使用

    JAXB的 eclipse插件

    JAXB(Java Architecture for XML Binding)是Java平台上的一个标准,它提供了一种在Java对象和XML文档之间进行映射的机制。Eclipse作为一款强大的Java集成开发环境,为开发者提供了丰富的插件支持,其中包括JAXB的...

    JAXBContext测试Java对象与xml的相互转换Demo

    JAXBContext是JAXB框架的核心,它扮演着一个工厂的角色,负责创建Unmarshaller(用于从XML到Java对象的转换)和Marshaller(用于从Java对象到XML的转换)。在这个"JAXBContext测试Java对象与xml的相互转换Demo"中,...

    jaxb api jar

    接着,可以使用`JAXBContext`来创建一个上下文,该上下文知道如何处理这些Java类。之后,`Marshaller`对象用于将Java对象序列化为XML,而`Unmarshaller`则用于从XML文档反序列化回Java对象。 在实际应用中,JAXB...

    JAXB2 jaxb-api.jar jaxb-xjc.jar jaxb-impl.jar activation.jar

    JAXB2,全称为Java Architecture for XML Binding 2,是Java平台上的一个标准技术,用于在XML和Java对象之间进行绑定。它允许开发者通过简单的API将XML文档转换为Java对象,反之亦然,大大简化了XML数据处理。JAXB2...

    javax.rar(jaxb-impl-2.3.0、jaxb-core-2.3.0、jaxb-api-2.3.0)

    标题中的"jaxb-impl-2.3.0、jaxb-core-2.3.0、jaxb-api-2.3.0"是JAXB的不同组件版本号,它们在处理XML到Java对象之间的转换时起到关键作用。在描述中提到的“Maven项目中缺少jaxb-api的异常报错”,通常指的是在运行...

Global site tag (gtag.js) - Google Analytics