我通过查看 tim_yates 提到的示例找到了解决方案。我能找到的最巧妙的方法是在 groovy.runtime.metaclass.wslite.soap 下添加一个 MetaClass,以便按照此处的说明进行自动 MetaClass 注册。
然后该类覆盖了委托给实际soap客户端的invokeMethod。实际上相当不错,但是经常使用的巫毒教有点太多了(就像大多数 AOP 编程恕我直言)
package groovy.runtime.metaclass.wslite.soap
import groovy.transform.ToString
import groovy.util.logging.Log4j
import mycomp.soap.InfrastructureException
import mycomp.soap.HttpLogger
import wslite.http.HTTPClientException
import wslite.soap.SOAPFaultException
import wslite.soap.SOAPResponse
/**
* Extension to the wslite client for logging and error handling.
* The package placement and class name is dictated by Groovy rules for Meta class loading (see http://groovy.codehaus.org/Using+the+Delegating+Meta+Class)
* Method invocation on SOAPClient will be proxied by this class which adds convenience methods.
*
*/
class SOAPClientMetaClass extends DelegatingMetaClass{
//Delegating logger in our package name, so log4j configuration does not need to know about this weird package
private final HttpLogger logger
SOAPClientMetaClass(MetaClass delegate){
super(delegate)
logger = new HttpLogger()
}
@Override
Object invokeMethod(Object object, String methodName, Object[] args) {
if(methodName == "send"){
withLogging {
withExceptionHandler {
return super.invokeMethod(object, "send", args)
}
}
} else {
return super.invokeMethod(object, methodName, args)
}
}
private SOAPResponse withLogging(Closure cl) {
SOAPResponse response = cl.call()
logger.log(response?.httpRequest, response?.httpResponse)
return response
}
private SOAPResponse withExceptionHandler(Closure cl) {
try {
return cl.call()
} catch (SOAPFaultException soapEx) {
logger.log(soapEx.httpRequest, soapEx.httpResponse)
def message = soapEx.hasFault() ? soapEx.fault.text() : soapEx.message
throw new InfrastructureException(message)
} catch (HTTPClientException httpEx) {
logger.log(httpEx.request, httpEx.response)
throw new InfrastructureException(httpEx.message)
}
}
}