我想监控传出请求的时间以跟踪我的应用程序中的 HTTP 集成。所有这些的公共(public)代码路径是 HttpClient.execute
所以这似乎是 AOP 的自然目标:
@Around("execution(* org.apache.http.client.HttpClient.execute(..)) && args(httpUriRequest)")
public Object timeApacheRequest(ProceedingJoinPoint proceedingJoinPoint, HttpUriRequest httpUriRequest) throws Throwable {
// etc.
}
但是,当我使用代理时,与 Spring HttpComponentsClientHttpRequestFactory
交互代码炸毁了它的instanceof
检查传入的代理。
Caused by: java.lang.IllegalArgumentException: 'httpClient' is not of type CloseableHttpClient Object of class [com.sun.proxy.$Proxy22] must be an instance of class org.apache.http.impl.client.CloseableHttpClient
运算符(operator)检查HttpComponentsClientHttpRequestFactory
:
public HttpComponentsClientHttpRequestFactory(HttpClient httpClient) {
Assert.notNull(httpClient, "'httpClient' must not be null");
Assert.isInstanceOf(CloseableHttpClient.class, httpClient, "'httpClient' is not of type CloseableHttpClient");
this.httpClient = (CloseableHttpClient) httpClient;
}
是否有更好的方法来构建我的代理来避免这个问题?
澄清一下,目前我使用 @EnableAspectJAutoProxy
建立当前代理。声明 bean 的配置类上的注释。
最佳答案
默认情况下,@EnableAspectJAutoProxy
(以及大多数生成代理的配置,@EnableTransactionManagement
、EnableAsync
等)使用 JDK proxies 。
JDK代理仅支持 super 接口(interface)。 newProxyInstance
返回的实例(创建 JDK 代理的入口点)将具有 Proxy
的父类(super class)型。
为了支持您的方面和建议,Spring 必须代理与您的连接点匹配的任何实例。由于默认配置,这些代理仅维护真实对象的 super 接口(interface)。 CloseableHttpClient
是一个抽象类。那就丢了。代理没有该类型,因此 instanceof
将失败。
相反,您可以将 @EnableAspectJAutoProxy#proxyTargetClass()
配置为 true
,以便 Spring 使用 CGLIB 来代理您的对象。 CGLIB 比 JDK 代理更强大。 CGLIB 可以子类化目标对象的类(除非其类是 final
或具有 private
构造函数)。
代理将成为 CloseableHttpClient
的子类型,并且 instanceof
可以工作。
关于java - Spring AOP 监控 Apache HttpClient.execute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33172485/