6

我以编程方式使用spring WebServiceTemplate 作为Web 服务客户端,即没有实例化spring 容器。我正在使用 Jaxb2Marshaller 进行编组/解组。在我的应用程序中,我创建了一个 SaajSoapMessageFactory 实例和一个 Jaxb2Marshaller 实例。我还创建了 WebServiceTemplate 的单个实例,并分配了之前创建的 SaajSoapMessageFactory 和 Jaxb2Marshaller 实例。

我创建的 WebServiceTemplate 以多线程方式使用,即多个线程可以同时调用 marshalSendAndReceive。我的问题是 - 我的配置线程安全吗?我担心 Jaxb2Marshaller。javadoc 说 Jaxb2Marshallers 不一定是线程安全的。如何在不重新初始化 Jaxb 上下文的情况下以线程安全的方式使用 Jaxb2Marshaller?

顺便说一句:查看spring 参考中的示例 spring-ws 配置让我相信 Jaxb2Marshaller 是线程安全的,但 Javadoc 似乎与此相矛盾。

4

3 回答 3

7

javadocJaxb2Marshaller没有以一种或另一种方式提到线程安全,所以我不确定你为什么认为它不是。如果它不是线程安全的,javadoc 会说得很清楚。

您的WebServiceTemplate,SaajSoapMessageFactoryJaxb2Marshaller单例配置非常好,并且完全是线程安全的。

于 2010-08-14T11:04:19.157 回答
2

The class org.springframework.oxm.jaxb.Jaxb2Marshaller is thread safe, since it creates for every marshalling event new instance of javax.xml.bind.Marshaller, see the original source code from Spring 5.2.6:

@Override
public void marshal(Object graph, Result result, @Nullable MimeContainer mimeContainer) throws XmlMappingException {
    try {
        Marshaller marshaller = createMarshaller();
        if (this.mtomEnabled && mimeContainer != null) {
            marshaller.setAttachmentMarshaller(new Jaxb2AttachmentMarshaller(mimeContainer));
        }
        if (StaxUtils.isStaxResult(result)) {
            marshalStaxResult(marshaller, graph, result);
        }
        else {
            marshaller.marshal(graph, result);
        }
    }
    catch (JAXBException ex) {
        throw convertJaxbException(ex);
    }
}

/**
 * Return a newly created JAXB marshaller.
 * <p>Note: JAXB marshallers are not necessarily thread-safe.
 * This method is public as of 5.2.
 * @since 5.2
 * @see #createUnmarshaller()
 */
public Marshaller createMarshaller() {
    try {
        Marshaller marshaller = getJaxbContext().createMarshaller();
        initJaxbMarshaller(marshaller);
        return marshaller;
    }
    catch (JAXBException ex) {
        throw convertJaxbException(ex);
    }
}

Similar situation is by Unmarshaller.

于 2021-09-11T10:48:05.300 回答
0

创建几个Jaxb2Marshaller(比如说五个),将它们放入一个池中(使用LinkedBlockingQueue)。创建线程时,将其传递给队列。

当一个线程需要一个时,take()一个来自队列/池。当池为空时,线程将阻塞此调用。

当一个线程使用完后Jaxb2Marshallerput()它会回到队列中,以便其他线程可以使用它。

如果您发现线程过于频繁地阻塞等待编组器,请向队列中添加更多线程(参见第一步)。这样,您可以轻松地调整池的大小(甚至使其可配置)。然后队列将自动分发它们。

于 2010-08-13T15:52:41.107 回答