我有一个Web服务,我使用客户端API中的服务接口对象操作SOAP头。
我需要将端口对象输入到BindingProvider
对象中。但我的port对象并没有直接子类化该类。那么JVM怎么可能不抱怨?
它也有效。没有ClassCastException的运行时错误
代码段:
public SearchDocument getSearchDocumentService(String wsdlUri, AuthBean auth){
SearchDocument_Service serv = null;
serv = SearchDocument_Service.getServiceInstance(wsdlUri);
SearchDocument searchDoc = serv.getSearchDocument();
populateAuthAndHandlerInfo((BindingProvider)searchDoc, auth);//how is it that jvm doesn't complain here
return searchDoc;
}
private void populateAuthAndHandlerInfo(BindingProvider port, AuthBean auth) {
Binding binding = port.getBinding();
List<Handler> handlerList = binding.getHandlerChain();
handlerList.add(new EDMSSoapAuthHandler());
binding.setHandlerChain(handlerList);
Map<String, Object> context = port.getRequestContext();
context.put("clientAuthInfo", auth);
}
SearchDocument.java:
@WebService(name = "SearchDocument", targetNamespace = "http://services.abc.com/Technology/SearchDocument/service/v1")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
ObjectFactory.class
})
public interface SearchDocument {
/**
*
* @param body
* @return
* returns com.abc.technology.search.document.client.v1.SearchOnMetadataResponse
* @throws AbcServiceException
* @throws AbcInvalidMessageException
* @throws AbcProducerApplicationException
*/
@WebMethod(action = "http://services.abc.com/Technology/SearchDocument/service/v1/soap11/SearchDocument/searchOnMetadata")
@WebResult(name = "SearchOnMetadataResponse", targetNamespace = "http://services.abc.com/Technology/SearchDocument/contract/v1", partName = "body")
public SearchOnMetadataResponse searchOnMetadata(
@WebParam(name = "SearchOnMetadata", targetNamespace = "http://services.abc.com/Technology/SearchDocument/contract/v1", partName = "body")
SearchOnMetadataRequest body)
throws AbcInvalidMessageException, AbcProducerApplicationException, AbcServiceException
;
}
答案 0 :(得分:4)
有几种方法可以回答您的问题。
但我的port对象并没有直接子类化该类。那么JVM怎么可能不抱怨呢?
嗯... SearchDocument
是一个界面。所以,当你打电话
SearchDocument searchDoc = serv.getSearchDocument();
然后searchDoc
是实现接口的给定类型的实例,但它没有指定这个具体类是什么。它可以是任何东西,包括实现SearchDocument
和BindingProvider
的具体类,因为它们都是接口,任何给定类型都可以同时实现多个接口。
所以这种必须这里发生了什么,对吗?
查看JAXWS规范可能会进一步启发您。你可以在https://jcp.org/en/jsr/detail?id=224下载它,但我会在第4.2.3章为你引用一些小块:
代理在运行时提供对服务端点接口的访问,而无需静态生成存根类。请参阅java.lang.reflect.Proxy 有关JDK支持的动态代理的更多信息
...
一致性(实现BindingProvider):代理实例必须实现javax-.xml.ws.BindingProvider
...
使用Service实例的getPort方法创建代理:T getPort(Class sei)返回指定SEI的代理
现在很容易将这些碎片重新组合在一起。
java.lang.reflect.Proxy
。在JVM中,有一个用于创建代理对象的API。 Proxy
对象(实例)是JVM中的一种特殊的野兽,可以在运行时动态创建,并且每个代理都可以符合任何给定的接口。它类似于在运行时创建Class
,而不是在编译时创建Proxy
,而无需编写其java源文件。当然,存在各种限制,但也存在许多可能性。
一个是对JVM说:&#34;嘿,给我一个SearchDocument
对象,同时实现接口BindingProvider
和Proxy
&#34;。 JVM也是如此。它会返回一个对象,其具体类为InvocationHandler
(通常为Proxy $ x,其中x为数字),并且是专门为实现这两个接口而设计的。
如果你想知道这在这一点上是否有用,那么不是没有,因为创建一个没有实现的类型是没有意义的。但是,有一种方法可以通过你编程的getPort
提供实现和行为(确切地说是另一种讨论)。
所以,在这一点上,我们从规范得到的是,如果我们在javax.xml.ws.Service
上调用BindingProvider
,那么结果必须是一个JDK代理,它必须实现{{1} }。
我敢打赌,正是在您致电:SearchDocument_Service
时会发生什么,它最终调用getPort
方法,并确保结果实现BindingProvider
,因为JAXWS说它必须这样做,以及您的SearchDocument
&#34;业务&#34;界面,因为它对你有用。