我在基于JBoss的Web应用程序中使用JAXBContext.newInstance操作。据我所知,这项行动是非常重量级的。我只需要Marshaller类的两个唯一实例。
我的初步建议是使用静态初始化程序块,只在类加载时初始化这两个实例:
public class MyWebApp {
private static Marshaller requestMarshaller;
private static Marshaller responseMarshaller;
static {
try {
// one time instance creation
requestMarshaller = JAXBContext.newInstance(Request.class).createMarshaller();
responseMarshaller = JAXBContext.newInstance(Response.class).createMarshaller();
} catch (JAXBException e) {
e.printStackTrace();
}
}
private void doSomething() {
requestMarshaller.marshall(...);
responseMarshaller.marshall(...);
...
}
}
如果这是一个合理的解决方案,那么我想我已经回答了我自己的问题,但我想知道这是否是正确的方法呢?
答案 0 :(得分:26)
JAXB实现(Metro,EclipseLink MOXy,Apache JaxMe等)通常在JAXBContext.newInstance
调用期间初始化其元数据。所有OXM工具都需要在某个时刻初始化映射元数据,并尝试最小化此操作的成本。由于不可能以零成本完成,因此最好只进行一次。 JAXBContext的实例是线程安全的,所以是的,你只需要创建一次。
从JAXB 2.2规范,第4.2节JAXB上下文:
避免涉及的开销 创建一个JAXBContext实例,一个 鼓励JAXB应用程序 重用JAXBContext实例。一个 抽象类的实现 需要JAXBContext 线程安全,因此,多个线程 应用程序可以共享相同的内容 JAXBContext实例。
Marshaller和Unmarshaller的实例不是线程安全的,不能在线程之间共享,它们是轻量级的。
答案 1 :(得分:8)
JAXBContext应该始终是静态的,它是线程安全的。
Marshallers和Unmarshallers很便宜而且不是线程安全的。您应该创建一次JAXBContext并为每个操作创建marshallers / unmarshallers
public class MyWebApp {
private static JAXBContext jaxbContext;
static {
try {
// one time instance creation
jaxbContext = JAXBContext.newInstance(Request.class, Response.class);
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
}
private void doSomething() {
jaxbContext.createMarshaller().marshall(...);
...
}
}
使用相同的编组器来编组所有内容(在创建上下文时添加所有类)。
答案 2 :(得分:4)
我最近使用JAXBContext.newInstance进行了一些性能测试,结果记录在这里。
http://app-inf.blogspot.com/2012/10/performance-tuning-logging-right-way.html
当一个线程调用时,使用一个包含~195个类的相当大的模式,完成需要大约400ms。当同时被20个线程调用时,它会引起cpu争用,并且需要大约5000ms才能完成。创建marshaller和对象序列化只是一个小对象~14ms。
答案 3 :(得分:0)
可以使用javax.xml.bind.JAXB。它有直接的Marshal和unmarshal方法。因此,您不必担心JAXB的实例创建。
e.g。 JAXB.unmarshal(inputStream / inputFile,outputClassExpected) 或JAXB.marshal(jaxbObject,xmlOutputFile / xmlOutputStream)
答案 4 :(得分:-1)
您应该为每个bean类创建单个JAXBContext
对象。见this