简体   繁体   English

使用AspectJ监视Spring Boot应用程序中REST调用的运行时间

[英]Using AspectJ to monitor run time of a REST call within Spring Boot app

I have a Spring Boot app with multiple classes that share a common HttpUtil class which makes Http requests. 我有一个带有多个类的Spring Boot应用程序,它们共享一个发出Http请求的公共HttpUtil类。 In the past, I have used AspectJ in the following: 过去,我在以下方面使用过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;
}

This worked fine, I'd match the getStatus() method with the @Around annotation, but the gateway structure now has code surrounding the httputil call, and I only want to profile the rest call. 这个工作正常,我将getStatus()方法与@Around注释匹配,但是网关结构现在具有围绕httputil调用的代码,并且我只想分析其余调用。 The new gateway method looks like: 新的网关方法如下所示:

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;
}

I realize I could re-factor this, or use the profiler on the HttpUtil class method itself, but how can I use AspectJ to match a snippet of code within an existing method? 我意识到我可以重构它,或者在HttpUtil类方法本身上使用探查器,但是如何使用AspectJ来匹配现有方法中的代码片段? As in, run the when the postEntity() call begins and after the postEntity() call finishes but before the method returns. postEntity() ,请在postEntity()调用开始时以及postEntity()调用完成之后方法返回之前运行。

I'm not too familiar with Pointcuts and other AspectJ properties. 我对Pointcuts和其他AspectJ属性不太熟悉。 All I'm trying to do is log the execution time, but I want to learn more about AspectJ. 我要做的只是记录执行时间,但是我想了解更多有关AspectJ的信息。

When you pick out a point in your program where you want to apply Advice and execute some extra code, like timing the postEntity() method call, you have to create join points and pointcut(s) for your chosen position. 当您在程序中选择要应用Advice并执行一些额外的代码的点时,例如对postEntity()方法进行计时,必须为所选位置创建连接点切入点 A pointcut defines what join points where your Advice will apply (where your timing code will start). 切入点定义了哪些连接点将在您的建议中应用(时序代码将在此处开始)。

So, I think your question is specifically about how to define a pointcut at the call of postEntity() in the ClassThatHasGetResponse class. 因此,我认为您的问题是关于如何在ClassThatHasGetResponse类中的postEntity()调用中定义切入点的。

Different ways to describe pointcuts are documented here and some nice pointcut examples are here . 不同的方法来描述切入点都记录在这里和一些不错的切入点例子是在这里

For your question, you might have a pointcut like this: 对于您的问题,您可能会有这样的切入点:

cflow(execution(Object ClassThatHasGetResponse.com.package.getResponse(..))) && call(* HttpUtil.postEntity(..))

The above pointcut defines the spot where the control flow of execution is inside the method getResponse() of the class ClassThatHasGetResponse and a method call is made to postEntity() with any return type and any parameters. 上面的切入点定义了执行控制流在类ClassThatHasGetResponse的方法getResponse()内的ClassThatHasGetResponse并使用任何返回类型和任何参数对postEntity()进行了方法调用。

You'll have to add this pointcut to @Around advice which captures the timing data, maybe like this: 您必须将此切入点添加到@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;
}

Since you're using Spring, it also may be worth noting that in Spring's support for AOP ( this is not the same as AspectJ, but it's easy to get confused about using one vs the other IMO, especially when first learning about AOP through Spring while using AspectJ ), a pointcut (composed of join points) is always a point of method execution, which simplifies a bit from the flexibility of AspectJ. 由于您使用的是Spring,因此在Spring对AOP的支持中( 这与AspectJ不同)也很值得注意,但这很容易使人对另一个IMO感到困惑,尤其是在通过Spring首次了解AOP时。使用AspectJ时 ,切入点(由连接点组成)始终是方法执行的要点,这简化了AspectJ的灵活性。 Source 资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM