2015-10-16 39 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的子類型將工作。