熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

基於Spring AOP實現對外接口的耗時監控

2013-11-23 20:21:16  來源: Java開源技術 

  AOP是Spring的核心Spring不但自身對多種框架的集成是基於AOP並且以非常方便的形式暴露給普通使用者以前用AOP不多主要是因為它以橫截面的方式插入到主流程中擔心導致主流程代碼不夠清晰定位問題不夠方便而在計費二期的項目裡需要一個很適合用AOP來做的功能就是要把對外接口和所調用的外部接口的耗時時間給記錄下來這個需求主要來自於計費一期的聯調常常發生系統間交互不夠順暢的情況這就需要看每個接口調用時間來判定是誰的問題

  計費中心是整個後台系統的中間環節與其他系統交互很多這樣的接口也很多如果在每個接口的調用前後加時間記錄比較繁瑣也影響主流程代碼的美觀因此比較優雅的方式是用AOP在不侵入原有代碼的情況下加上對接口調用的監控並且可以在不需要的時候很容易移除今天嘗試了一下感覺還挺好用下面講述一下實施步驟

  )引入包依賴

  本項目基於maven構建因此加上包依賴比較方便我需要的AOP依賴庫有以下三個

  [xhtml]

  <dependency>

  <groupId>orgspringframework</groupId>

  <artifactId>springaop</artifactId>

  <version></version>

  </dependency>

  <dependency>

  <groupId>orgaspectj</groupId>

  <artifactId>aspectjweaver</artifactId>

  <version></version>

  </dependency>

  <dependency>

  <groupId>orgaspectj</groupId>

  <artifactId>aspectjrt</artifactId>

  <version></version>

  </dependency>

  <dependency>

  <groupId>orgspringframework</groupId>

  <artifactId>springaop</artifactId>

  <version></version>

  </dependency>

  <dependency>

  <groupId>orgaspectj</groupId>

  <artifactId>aspectjweaver</artifactId>

  <version></version>

  </dependency>

  <dependency>

  <groupId>orgaspectj</groupId>

  <artifactId>aspectjrt</artifactId>

  <version></version>

  </dependency>

  )加上AOP的Spring配置文件

  billingspringaopxml:

  [xhtml]

  <?xml version= encoding=UTF?>

  <beans xmlns=

  xmlns:xsi=instance

  xmlns:aop=

  xmlns:tx=

  xsi:schemaLocation= beansxsd

  aopxsd

  txxsd>

  <bean id=openApiLogAspect class=bubillingframeworkaopOpenApiLogAspect>

  </bean>

  <aop:config>

  <! 配置aspect切面類 >

  <aop:aspect ref=openApiLogAspect>

  <! 配置pointcut即切入點對哪些類的哪些方法起到AOP的作用 >

  <aop:pointcut id=EsbPriceService

  expression=execution(* productEsbPriceService*()) />

  <aop:pointcut id=EsbProductService

  expression=execution(* productEsbProductService*()) />

  <aop:pointcut id=IAuthorizeControllerService

  expression=execution(* comalibababsspcserverremotingIAuthorizeControllerService*()) />

  <aop:pointcut id=IOpenApiOrderItemService

  expression=execution(* llectIOpenApiOrderItemService*()) />

  <aop:pointcut id=IOpenApiBillingCollectService

  expression=execution(* llectIOpenApiBillingCollectService*()) />

  <aop:pointcut id=IOpenApiInvoiceService

  expression=execution(* bubillingapiinvoiceIOpenApiInvoiceService*()) />

  <aop:pointcut id=IOpenApiChargeProductInfoService

  expression=execution(* llectIOpenApiChargeProductInfoService*()) />

  <! 配置advice這裡采用在業務方法執行前後進行攔截 >

  <aop:around method=logExecuteTime pointcutref=EsbPriceService />

  <aop:around method=logExecuteTime pointcutref=EsbProductService />

  <aop:around method=logExecuteTime pointcutref=IAuthorizeControllerService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiOrderItemService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiBillingCollectService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiInvoiceService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiChargeProductInfoService />

  </aop:aspect>

  </aop:config>

  </beans>

  <?xml version= encoding=UTF?>

  <beans xmlns=

  xmlns:xsi=instance

  xmlns:aop=

  xmlns:tx=

  xsi:schemaLocation= beansxsd

  aopxsd

  txxsd>

  <bean id=openApiLogAspect class=bubillingframeworkaopOpenApiLogAspect>

  </bean>

  <aop:config>

  <! 配置aspect切面類 >

  <aop:aspect ref=openApiLogAspect>

  <! 配置pointcut即切入點對哪些類的哪些方法起到AOP的作用 >

  <aop:pointcut id=EsbPriceService

  expression=execution(* productEsbPriceService*()) />

  <aop:pointcut id=EsbProductService

  expression=execution(* productEsbProductService*()) />

  <aop:pointcut id=IAuthorizeControllerService

  expression=execution(* comalibababsspcserverremotingIAuthorizeControllerService*()) />

  <aop:pointcut id=IOpenApiOrderItemService

  expression=execution(* llectIOpenApiOrderItemService*()) />

  <aop:pointcut id=IOpenApiBillingCollectService

  expression=execution(* llectIOpenApiBillingCollectService*()) />

  <aop:pointcut id=IOpenApiInvoiceService

  expression=execution(* bubillingapiinvoiceIOpenApiInvoiceService*()) />

  <aop:pointcut id=IOpenApiChargeProductInfoService

  expression=execution(* llectIOpenApiChargeProductInfoService*()) />

  <! 配置advice這裡采用在業務方法執行前後進行攔截 >

  <aop:around method=logExecuteTime pointcutref=EsbPriceService />

  <aop:around method=logExecuteTime pointcutref=EsbProductService />

  <aop:around method=logExecuteTime pointcutref=IAuthorizeControllerService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiOrderItemService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiBillingCollectService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiInvoiceService />

  <aop:around method=logExecuteTime pointcutref=IOpenApiChargeProductInfoService />

  </aop:aspect>

  </aop:config>

  </beans>

  我是基於配置完成AOP接入這樣做的好處是不需要對原有主流程代碼有任何浸入並且也比較容易移除本AOP的攔截這段代碼主要就是配置aspectpointcut和advice

  )編寫監控耗時的advice

  OpenApiLogAspect:

  [java]

  public class OpenApiLogAspect {

  private static LoggerService logger = LoggerFactorygetLogger(OpenApiLogAspectclass);

  public Object logExecuteTime(ProceedingJoinPoint joinPoint) throws Throwable{

  Date start = new Date();

  try{

  return joinPointproceed(joinPointgetArgs());

  }catch(Exception err){

  throw err;

  }finally{

  Date end = new Date();

  (OpenApiExecuteTime:+joinPointgetSignature()getName()+ takes +(endgetTime()startgetTime())+ms);

  }

  }

  }

  public class OpenApiLogAspect {

  private static LoggerService logger = LoggerFactorygetLogger(OpenApiLogAspectclass);

  public Object logExecuteTime(ProceedingJoinPoint joinPoint) throws Throwable{

  Date start = new Date();

  try{

  return joinPointproceed(joinPointgetArgs());

  }catch(Exception err){

  throw err;

  }finally{

  Date end = new Date();

  (OpenApiExecuteTime:+joinPointgetSignature()getName()+ takes +(endgetTime()startgetTime())+ms);

  }

  }

  }

  此段代碼就是基於around的方式來攔截接口調用在實際調用的前後加上時間記錄並最後在日志裡打印出時間差其中joinPointproceed(joinPointgetArgs());是對實際接口的調用

  )使監控可以配置化

  此功能只會在調試階段使用並不需要在生產環境中運行因此需要可以配置是否監控接口實施這個配置化很簡單只需要通過配置決定是否把aop spring的配置文件加入到容器裡就可以了因此在總容器applicationContextxmlvm裡加上如下代碼

  #if(${monitor_openapi_showTime}==true)

  <import resource=classpath*:bean/billingspringaopxml />

  #end

  在編譯打包過程中會根據變量monitor_openapi_showTime來決定是否把billingspringaopxml引入進來

  )運行效果

  在監控開啟的情況下若發生接口調用能從日志裡看到如下記錄

   :: [OpenApiLogAspectjava:] [bubillingframeworkaopOpenApiLogAspect] INFO bubillingframeworkaopOpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes ms

   :: [OpenApiLogAspectjava:] [bubillingframeworkaopOpenApiLogAspect] INFO bubillingframeworkaopOpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes ms

   :: [OpenApiLogAspectjava:] [bubillingframeworkaopOpenApiLogAspect] INFO bubillingframeworkaopOpenApiLogAspect :: OpenApiExecuteTime:installOrderItem takes ms


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28361.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.