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