基于Spring AOP实现对外接口的耗时监控

本文介绍如何利用Spring AOP实现对外部接口调用时间的监控,包括引入依赖、配置Spring、编写监控耗时的advice及配置化等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AOP是Spring的核心,Spring不但自身对多种框架的集成是基于AOP,并且以非常方便的形式暴露给普通使用者。以前用AOP不多,主要是因为它以横截面的方式插入到主流程中,担心导致主流程代码不够清晰,定位问题不够方便,而在计费二期的项目里需要一个很适合用AOP来做的功能,就是要把对外接口和所调用的外部接口的耗时时间给记录下来,这个需求主要来自于计费一期的联调,常常发生系统间交互不够顺畅的情况,这就需要看每个接口调用时间来判定是谁的问题。

计费中心是整个后台系统的中间环节,与其他系统交互很多,这样的接口也很多,如果在每个接口的调用前后加时间记录比较繁琐,也影响主流程代码的美观,因此比较优雅的方式是用AOP,在不侵入原有代码的情况下,加上对接口调用的监控,并且可以在不需要的时候很容易移除。今天尝试了一下,感觉还挺好用,下面讲述一下实施步骤:

1)引入包依赖

本项目基于maven构建,因此加上包依赖比较方便,我需要的AOP依赖库有以下三个:

[xhtml] view plain copy
  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-aop</artifactId>
  4. <version>2.5.6</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.aspectj</groupId>
  8. <artifactId>aspectjweaver</artifactId>
  9. <version>1.6.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.aspectj</groupId>
  13. <artifactId>aspectjrt</artifactId>
  14. <version>1.6.1</version>
  15. </dependency>

2)加上AOP的Spring配置文件

billing-spring-aop.xml:

[xhtml] view plain copy
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
  7. http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
  8. http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
  9. <beanid="openApiLogAspect"class="com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect">
  10. </bean>
  11. <aop:config>
  12. <!--配置aspect切面类-->
  13. <aop:aspectref="openApiLogAspect">
  14. <!--配置pointcut,即切入点,对哪些类的哪些方法起到AOP的作用-->
  15. <aop:pointcutid="EsbPriceService"
  16. expression="execution(*org.esb.biz.product.EsbPriceService.*(..))"/>
  17. <aop:pointcutid="EsbProductService"
  18. expression="execution(*org.esb.biz.product.EsbProductService.*(..))"/>
  19. <aop:pointcutid="IAuthorizeControllerService"
  20. expression="execution(*com.alibaba.bss.pc2.server.remoting.IAuthorizeControllerService.*(..))"/>
  21. <aop:pointcutid="IOpenApiOrderItemService"
  22. expression="execution(*com.alibaba.itbu.billing.api.collect.IOpenApiOrderItemService.*(..))"/>
  23. <aop:pointcutid="IOpenApiBillingCollectService"
  24. expression="execution(*com.alibaba.itbu.billing.api.collect.IOpenApiBillingCollectService.*(..))"/>
  25. <aop:pointcutid="IOpenApiInvoiceService"
  26. expression="execution(*com.alibaba.itbu.billing.api.invoice.IOpenApiInvoiceService.*(..))"/>
  27. <aop:pointcutid="IOpenApiChargeProductInfoService"
  28. expression="execution(*com.alibaba.itbu.billing.api.collect.IOpenApiChargeProductInfoService.*(..))"/>
  29. <!--配置advice,这里采用在业务方法执行前后进行拦截-->
  30. <aop:aroundmethod="logExecuteTime"pointcut-ref="EsbPriceService"/>
  31. <aop:aroundmethod="logExecuteTime"pointcut-ref="EsbProductService"/>
  32. <aop:aroundmethod="logExecuteTime"pointcut-ref="IAuthorizeControllerService"/>
  33. <aop:aroundmethod="logExecuteTime"pointcut-ref="IOpenApiOrderItemService"/>
  34. <aop:aroundmethod="logExecuteTime"pointcut-ref="IOpenApiBillingCollectService"/>
  35. <aop:aroundmethod="logExecuteTime"pointcut-ref="IOpenApiInvoiceService"/>
  36. <aop:aroundmethod="logExecuteTime"pointcut-ref="IOpenApiChargeProductInfoService"/>
  37. </aop:aspect>
  38. </aop:config>
  39. </beans>

我是基于配置完成AOP接入,这样做的好处是不需要对原有主流程代码有任何浸入,并且也比较容易移除本AOP的拦截,这段代码主要就是配置aspect、pointcut和advice

3)编写监控耗时的advice

OpenApiLogAspect:

[java] view plain copy
  1. publicclassOpenApiLogAspect{
  2. privatestaticLoggerServicelogger=LoggerFactory.getLogger(OpenApiLogAspect.class);
  3. publicObjectlogExecuteTime(ProceedingJoinPointjoinPoint)throwsThrowable{
  4. Datestart=newDate();
  5. try{
  6. returnjoinPoint.proceed(joinPoint.getArgs());
  7. }catch(Exceptionerr){
  8. throwerr;
  9. }finally{
  10. Dateend=newDate();
  11. logger.info("OpenApiExecuteTime:"+joinPoint.getSignature().getName()+"takes"+(end.getTime()-start.getTime())+"ms");
  12. }
  13. }
  14. }

此段代码就是基于around的方式来拦截接口调用,在实际调用的前后加上时间记录,并最后在日志里打印出时间差。其中joinPoint.proceed(joinPoint.getArgs());是对实际接口的调用。

4)使监控可以配置化

此功能只会在调试阶段使用,并不需要在生产环境中运行,因此需要可以配置是否监控接口。实施这个配置化很简单,只需要通过配置决定是否把aop spring的配置文件加入到容器里就可以了,因此在总容器applicationContext.xml.vm里加上如下代码:

#if(${monitor_openapi_showTime}=="true")
<import resource="classpath*:bean/billing-spring-aop.xml" />
#end

在编译打包过程中会根据变量monitor_openapi_showTime来决定是否把billing-spring-aop.xml引入进来

5)运行效果

在监控开启的情况下,若发生接口调用,能从日志里看到如下记录:

2010-01-08 18:30:13,197 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 71ms
2010-01-08 18:30:27,188 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 0ms
2010-01-08 18:30:37,838 [OpenApiLogAspect.java:20] [com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect] INFO com.alibaba.itbu.billing.framework.aop.OpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes 1ms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值