ITKeyword,专注技术干货聚合推荐

注册 | 登录

JAXB(三)——JAXBContext及其优化

234390216 分享于

2021腾讯云限时秒杀,爆款1核2G云服务器298元/3年!(领取2860元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1062

2021阿里云最低价产品入口+领取代金券(老用户3折起),
入口地址https://www.aliyun.com/minisite/goods

推荐:使用ViewStub 优化XML布局 提高性能

 Android 经常有些布局不长被用到 这些界面每次被调用 都会重新建立一个新的Activity 所以就有了ViewStub   比如说横竖屏切换的时候 使用ViewStub 只需要设置一

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文件中如下定义: ResponsePerson 然后后续就可以用对应的JAXBContext来进行相应的Marshal和UnMarshal操作了。通过指定包名称创建JAXBContext的方式可以把程序中各种可能的场景中需要使用到的Class都初始化到一个JAXBContext中,这样可以保证这个JAXBContext可以在各种可能的场景下都能满足需求,JAXBContext的初始化是非常耗CPU的,重用JAXBContext有助于提升性能。另一方面我们如果在某一时刻调整使用的Class时可以不用修改源码,直接修改jaxb.index文件中定义的Class即可,这可比修改源码要简单的多。 为了保证文章的完整性,以下给出一个基于包名称初始化JAXBContext的完整示例。 @Testpublic 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;} @XmlRootElementpublic 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} ResponsePerson 生成的XML如下: <response>

<returnCode>100</returnCode>

<message>AAAA</message>

<data>

<dept id="1">

<name>张三</name>

</dept>

</data></response> 使用直接指定class创建JAXBContext的方式我们的代码可以是如下这样: @Testpub

推荐:parsing XML: unbound prefix

在LinearLayout添加滚动效果的时,代码如下: <xml version="1.0" encoding="utf-8"><ScrollView

android:layout_width="fill_parent"

android:layout_h

lic 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.jaxb和com.xxx.jaxb2两个package。 JAXBContext jaxbContext = JAXBContext.newInstance("com.xxx.jaxb:com.xxx.jaxb2"); 性能优化 每次在创建JAXBContext实例时,JAXBContext内部都需要维护好Java类和XML之间的映射关系,这个操作是十分消耗性能的。幸运的是JAXBContext是线程安全的,可以共享。关于JAXBContext存在的性能问题笔者准备了如下测试代码: @Testpublic 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对象是线程不安全的,切勿进行重用。

推荐:tomcat server.xml中性能优化的几个配置说明

  maxThreads:Tomcat可创建的最大的线程数,每一个线程处理一个请求(最多同时处理150个连接);   minSpareThreads:最小备用线程数,tomcat启动时的初始化的线程

JAXBContext介绍及性能优化 摘要 本文主要介绍基于package创建JAXBContext,以及阐述JAXBContext存在的性能问题及其优化。 JAXBContext介绍 JAXBContext是我们在使用JAXB时的入口类,我们需要通

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。