使用 AspectJ 监视 运行 启动应用程序中 REST 调用的时间
Using AspectJ to monitor run time of a REST call within Spring Boot app
我有一个 Spring 启动应用程序,其中包含多个 classes,它们共享一个通用的 HttpUtil class,它发出 Http 请求。过去,我在以下方面使用了 AspectJ:
@Around("execution(* com.gateway.TestGateway.getStatus(..))")
public Object GatewayStatus(ProceedingJoinPoint pjp) throws Throwable {
StopWatch watch = new StopWatch();
watch.start();
Object output = pjp.proceed();
watch.stop();
log.error("Call took - [" + (watch.getTime()) + "]ms");
return output;
}
这很好用,我将 getStatus()
方法与 @Around
注释匹配,但网关结构现在有围绕 httputil 调用的代码,我只想分析其余调用.新的网关方法如下所示:
final HttpUtil httpUtil; //Constructor injected by Spring.
public ResponseEntity<String> getResponse(final String serviceUrl, final HttpEntity<String> httpEntity) throws Exception {
ResponseEntity<String> response = null;
//Code here to verify the Entity
try{
response = httpUtil.postEntity(serviceUrl, httpEntity, String.class,
httpUtil.getRestTemplate());
//Logic here to work on the response.
}
catch(Exception e){
log.error("Error occurred");
}
return response;
}
我知道我可以重构它,或者在 HttpUtil class 方法本身上使用探查器,但是我如何使用 AspectJ 来匹配现有方法中的代码片段?如,运行 postEntity()
调用开始和 postEntity()
调用完成后 但 在方法 returns 之前 [=] 18=]
我不太熟悉切入点和其他 AspectJ 属性。我想做的只是记录执行时间,但我想了解有关 AspectJ 的更多信息。
当您在程序中选择要应用建议并执行一些额外代码的点时,例如为 postEntity()
方法调用计时,您必须创建 连接点 和 pointcut(s) 为您选择的位置。切入点定义了您的建议将应用的连接点(您的计时代码将从哪里开始)。
因此,我认为您的问题具体是关于如何在 ClassThatHasGetResponse
class.
中的 postEntity()
调用处定义切入点
记录了描述切入点的不同方法 here and some nice pointcut examples are here。
对于你的问题,你可能有这样的切入点:
cflow(execution(Object ClassThatHasGetResponse.com.package.getResponse(..))) && call(* HttpUtil.postEntity(..))
上面的切入点定义了执行控制流在 class ClassThatHasGetResponse
的方法 getResponse()
内部的位置,并且对 postEntity()
进行了方法调用使用任何 return 类型和任何参数。
您必须将此切入点添加到捕获计时数据的@Around 建议,可能像这样:
@Around("cflow(execution(Object ClassThatHasGetResponse.com.package.getResponse(..))) && call(* HttpUtil.postEntity(..))")
public Object GatewayStatus(ProceedingJoinPoint pjp) throws Throwable {
StopWatch watch = new StopWatch();
watch.start();
Object output = pjp.proceed();
watch.stop();
log.error("Call took - [" + (watch.getTime()) + "]ms");
return output;
}
由于您使用的是 Spring,可能还值得注意的是 Spring 对 AOP 的支持(这与 AspectJ 不同,但它是很容易混淆使用一个和另一个 IMO,特别是当第一次通过 Spring 学习 AOP 而使用 AspectJ 时),切入点(由连接点组成)始终是方法执行的一个点,这简化了 AspectJ 的灵活性。 Source
我有一个 Spring 启动应用程序,其中包含多个 classes,它们共享一个通用的 HttpUtil class,它发出 Http 请求。过去,我在以下方面使用了 AspectJ:
@Around("execution(* com.gateway.TestGateway.getStatus(..))")
public Object GatewayStatus(ProceedingJoinPoint pjp) throws Throwable {
StopWatch watch = new StopWatch();
watch.start();
Object output = pjp.proceed();
watch.stop();
log.error("Call took - [" + (watch.getTime()) + "]ms");
return output;
}
这很好用,我将 getStatus()
方法与 @Around
注释匹配,但网关结构现在有围绕 httputil 调用的代码,我只想分析其余调用.新的网关方法如下所示:
final HttpUtil httpUtil; //Constructor injected by Spring.
public ResponseEntity<String> getResponse(final String serviceUrl, final HttpEntity<String> httpEntity) throws Exception {
ResponseEntity<String> response = null;
//Code here to verify the Entity
try{
response = httpUtil.postEntity(serviceUrl, httpEntity, String.class,
httpUtil.getRestTemplate());
//Logic here to work on the response.
}
catch(Exception e){
log.error("Error occurred");
}
return response;
}
我知道我可以重构它,或者在 HttpUtil class 方法本身上使用探查器,但是我如何使用 AspectJ 来匹配现有方法中的代码片段?如,运行 postEntity()
调用开始和 postEntity()
调用完成后 但 在方法 returns 之前 [=] 18=]
我不太熟悉切入点和其他 AspectJ 属性。我想做的只是记录执行时间,但我想了解有关 AspectJ 的更多信息。
当您在程序中选择要应用建议并执行一些额外代码的点时,例如为 postEntity()
方法调用计时,您必须创建 连接点 和 pointcut(s) 为您选择的位置。切入点定义了您的建议将应用的连接点(您的计时代码将从哪里开始)。
因此,我认为您的问题具体是关于如何在 ClassThatHasGetResponse
class.
postEntity()
调用处定义切入点
记录了描述切入点的不同方法 here and some nice pointcut examples are here。
对于你的问题,你可能有这样的切入点:
cflow(execution(Object ClassThatHasGetResponse.com.package.getResponse(..))) && call(* HttpUtil.postEntity(..))
上面的切入点定义了执行控制流在 class ClassThatHasGetResponse
的方法 getResponse()
内部的位置,并且对 postEntity()
进行了方法调用使用任何 return 类型和任何参数。
您必须将此切入点添加到捕获计时数据的@Around 建议,可能像这样:
@Around("cflow(execution(Object ClassThatHasGetResponse.com.package.getResponse(..))) && call(* HttpUtil.postEntity(..))")
public Object GatewayStatus(ProceedingJoinPoint pjp) throws Throwable {
StopWatch watch = new StopWatch();
watch.start();
Object output = pjp.proceed();
watch.stop();
log.error("Call took - [" + (watch.getTime()) + "]ms");
return output;
}
由于您使用的是 Spring,可能还值得注意的是 Spring 对 AOP 的支持(这与 AspectJ 不同,但它是很容易混淆使用一个和另一个 IMO,特别是当第一次通过 Spring 学习 AOP 而使用 AspectJ 时),切入点(由连接点组成)始终是方法执行的一个点,这简化了 AspectJ 的灵活性。 Source