2015-10-16 40 views
2

我想监视传出请求的时间以跟踪我的应用程序中的HTTP集成。常见的代码路径,个个是HttpClient.execute,这样似乎对AOP的自然目标:Apache HttpClient.exe的Spring AOP监视执行

@Around("execution(* org.apache.http.client.HttpClient.execute(..)) && args(httpUriRequest)") 
public Object timeApacheRequest(ProceedingJoinPoint proceedingJoinPoint, HttpUriRequest httpUriRequest) throws Throwable { 
    // etc. 
} 

然而,当我用我的代理,互动春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; 
} 

有我为const更好的办法ruct我的代理,将消除这个问题?

为了澄清,目前我在声明bean的配置类上使用@EnableAspectJAutoProxy批注建立当前代理。

+0

你怎么声明代理? - 澄清 - aspectj:autoproxy或类似的东西? –

+0

@DaveG,您的评论独自向我发送了正确的方向 - 它让我发现了注释的“proxyTargetClass”属性,这看起来正是我所需要的。我想知道你能否更好地解释它的用法是正确的还是不正确的? – jwilner

回答

1

默认情况下,@EnableAspectJAutoProxy(以及大多数生成代理的配置,@EnableTransactionManagement,EnableAsync等)使用JDK proxies

JDK代理只支持超级接口。由newProxyInstance(创建JDK代理的入口点)返回的实例将具有超类型Proxy

为了支持您的方面和建议,Spring必须代理与您的连接点匹配的任何实例。由于默认配置,这些代理只能维护真实对象的超级接口。 CloseableHttpClient是一个抽象类。这是失败的。该代理没有该类型,因此instanceof将失败。

相反,您可以将@EnableAspectJAutoProxy#proxyTargetClass()配置为true,以便Spring使用CGLIB代理您的对象。 CGLIB比JDK代理更强大。 CGLIB可以继承你的目标对象的类(除非它的类是final或者有一个private的构造函数)。

然后代理将是CloseableHttpClientinstanceof的子类型将工作。