Spring Apache的AOP监控HttpClient.execute
Spring AOP monitoring of Apache HttpClient.execute
我想监控传出请求的时间以跟踪我的应用程序中的 HTTP 集成。所有这些的公共代码路径是 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
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;
}
我有没有更好的方法来构建我的代理来避免这个问题?
澄清一下,目前我在声明 bean 的配置 class 上使用 @EnableAspectJAutoProxy
注释建立当前代理。
默认情况下,@EnableAspectJAutoProxy
(以及大多数生成代理的配置,@EnableTransactionManagement
、EnableAsync
等)使用 JDK proxies.
JDK代理只支持超级接口。 newProxyInstance
返回的实例(创建 JDK 代理的入口点)将具有超类型 Proxy
。
为了支持您的方面和建议,Spring 必须代理任何与您的连接点匹配的实例。由于默认配置,这些代理只维护真实对象的超级接口。 CloseableHttpClient
是一个摘要 class。那是迷路了。代理没有该类型,因此 instanceof
将失败。
相反,您可以将 @EnableAspectJAutoProxy#proxyTargetClass()
配置为 true
,以便 Spring 使用 CGLIB 来代理您的对象。 CGLIB 比 JDK 代理更强大。 CGLIB 可以子class 目标对象的class(除非它的class 是final
或者有一个private
构造函数)。
代理将是 CloseableHttpClient
的子类型并且 instanceof
可以工作。
我想监控传出请求的时间以跟踪我的应用程序中的 HTTP 集成。所有这些的公共代码路径是 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
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;
}
我有没有更好的方法来构建我的代理来避免这个问题?
澄清一下,目前我在声明 bean 的配置 class 上使用 @EnableAspectJAutoProxy
注释建立当前代理。
默认情况下,@EnableAspectJAutoProxy
(以及大多数生成代理的配置,@EnableTransactionManagement
、EnableAsync
等)使用 JDK proxies.
JDK代理只支持超级接口。 newProxyInstance
返回的实例(创建 JDK 代理的入口点)将具有超类型 Proxy
。
为了支持您的方面和建议,Spring 必须代理任何与您的连接点匹配的实例。由于默认配置,这些代理只维护真实对象的超级接口。 CloseableHttpClient
是一个摘要 class。那是迷路了。代理没有该类型,因此 instanceof
将失败。
相反,您可以将 @EnableAspectJAutoProxy#proxyTargetClass()
配置为 true
,以便 Spring 使用 CGLIB 来代理您的对象。 CGLIB 比 JDK 代理更强大。 CGLIB 可以子class 目标对象的class(除非它的class 是final
或者有一个private
构造函数)。
代理将是 CloseableHttpClient
的子类型并且 instanceof
可以工作。