如何将不属于 BindingProvider 子类的 object 显式转换为 BindingProvider object?
How is an object which does not subclass BindingProvider be casted explicitly into a BindingProvider object?
我有一个 Web 服务,我在其中使用客户端 API 中的服务接口 object 来操作 SOAP headers。
我需要将端口 object 类型转换为 BindingProvider
object。但是我的端口object并没有直接subclass那个class。那么 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
;
}
有几种方法可以回答您的问题。
从高层次的角度来看
But my port object does not directly subclass that class. So how is it possible the JVM doesn't complain ?
嗯... SearchDocument
是一个接口。所以,当你打电话给
SearchDocument searchDoc = serv.getSearchDocument();
那么 searchDoc
是实现该接口的给定类型的实例,但没有指定具体的 class 是什么。它可以是任何东西,包括实现 SearchDocument
和 BindingProvider
的具体 class,因为两者都是接口,任何给定类型都可以同时自由实现多个接口。
所以这种一定是这里发生的事情吧?
来自 JAX WS 规范
查看 JAXWS 规范可能会进一步启发您。您可以在 https://jcp.org/en/jsr/detail?id=224 下载它,但我会在第 4.2.3 章为您引用一些要点:
Proxies provide access to service endpoint interfaces at runtime without requiring static generation of a stubclass. See java.lang.reflect.Proxy
for more information on dynamic proxies as supported by the JDK
...
Conformance (Implementing BindingProvider): An instance of a proxy MUST implement javax-.xml.ws.BindingProvider
...
A proxy is created using the getPort methods of a Service instance: T getPort(Class sei) Returns a proxy for the specified SEI
现在很容易将各个部分重新组合在一起。
什么是 java.lang.reflect.Proxy
东西。
在JVM 中,有一个API 用于创建代理对象。 Proxy
对象(实例)是 JVM 中的一种特殊类型,可以在运行时动态创建,并且可以使每个代理符合任何给定的接口。这就像在运行时创建一个 Class
,而不是在编译时,并且不必编写其 java 源文件。当然,有种种限制,但也有很多可能性。
一个是对 JVM 说:"hey, give me a Proxy
object that implements the interfaces SearchDocument
and BindingProvider
at the same time"。 JVM 也是如此。它返回一个对象,其具体 class 是 Proxy
(通常是 Proxy$x,其中 x 是一个数字),并且是专门为实现这两个接口而设计的。
如果您想知道此时这是否有任何用处,那么不,它没有用,因为创建一个没有实现的类型有点毫无意义。但是有一种方法可以通过您编程的所谓 InvocationHandler
来提供实现和行为(另一个讨论究竟如何)。
所以,在这一点上,我们从规范中得到的是,如果我们在 javax.xml.ws.Service
上调用 getPort
,那么结果必须是一个 JDK 代理,它必须还实施 BindingProvider
.
回到你的案例
我敢打赌,当您调用 SearchDocument_Service
时,它最终会调用 getPort
方法,并确保结果实现 BindingProvider
,因为 JAXWS说它必须这样做,还有你的 SearchDocument
"business" 界面,因为它对你有用。
我有一个 Web 服务,我在其中使用客户端 API 中的服务接口 object 来操作 SOAP headers。
我需要将端口 object 类型转换为 BindingProvider
object。但是我的端口object并没有直接subclass那个class。那么 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
;
}
有几种方法可以回答您的问题。
从高层次的角度来看
But my port object does not directly subclass that class. So how is it possible the JVM doesn't complain ?
嗯... SearchDocument
是一个接口。所以,当你打电话给
SearchDocument searchDoc = serv.getSearchDocument();
那么 searchDoc
是实现该接口的给定类型的实例,但没有指定具体的 class 是什么。它可以是任何东西,包括实现 SearchDocument
和 BindingProvider
的具体 class,因为两者都是接口,任何给定类型都可以同时自由实现多个接口。
所以这种一定是这里发生的事情吧?
来自 JAX WS 规范
查看 JAXWS 规范可能会进一步启发您。您可以在 https://jcp.org/en/jsr/detail?id=224 下载它,但我会在第 4.2.3 章为您引用一些要点:
Proxies provide access to service endpoint interfaces at runtime without requiring static generation of a stubclass. See java.lang.reflect.Proxy for more information on dynamic proxies as supported by the JDK
...
Conformance (Implementing BindingProvider): An instance of a proxy MUST implement javax-.xml.ws.BindingProvider
...
A proxy is created using the getPort methods of a Service instance: T getPort(Class sei) Returns a proxy for the specified SEI
现在很容易将各个部分重新组合在一起。
什么是 java.lang.reflect.Proxy
东西。
在JVM 中,有一个API 用于创建代理对象。 Proxy
对象(实例)是 JVM 中的一种特殊类型,可以在运行时动态创建,并且可以使每个代理符合任何给定的接口。这就像在运行时创建一个 Class
,而不是在编译时,并且不必编写其 java 源文件。当然,有种种限制,但也有很多可能性。
一个是对 JVM 说:"hey, give me a Proxy
object that implements the interfaces SearchDocument
and BindingProvider
at the same time"。 JVM 也是如此。它返回一个对象,其具体 class 是 Proxy
(通常是 Proxy$x,其中 x 是一个数字),并且是专门为实现这两个接口而设计的。
如果您想知道此时这是否有任何用处,那么不,它没有用,因为创建一个没有实现的类型有点毫无意义。但是有一种方法可以通过您编程的所谓 InvocationHandler
来提供实现和行为(另一个讨论究竟如何)。
所以,在这一点上,我们从规范中得到的是,如果我们在 javax.xml.ws.Service
上调用 getPort
,那么结果必须是一个 JDK 代理,它必须还实施 BindingProvider
.
回到你的案例
我敢打赌,当您调用 SearchDocument_Service
时,它最终会调用 getPort
方法,并确保结果实现 BindingProvider
,因为 JAXWS说它必须这样做,还有你的 SearchDocument
"business" 界面,因为它对你有用。