Spring AOP 切面編程記錄日誌和接口執行時間
如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群裏有阿裏大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。
對於這個問題,想到了使用動態代理的方式統一記錄方法的執行時間並打印日誌,這樣就能很直觀、方便的看到每個接口的執行時間了。
由於使用的是spring框架,對象都是由spring統一管理的,所以最後使用的是?Spring AOP 切面編程來統一記錄接口的執行時間,具體代碼如下(基於註解的方式):
@Component @Aspect public class AopLoggerAspect { private static final Logger logger = Logger.getLogger(AopLoggerAspect.class); @Pointcut("execution(public * com.iflytek.credit.platform.*.service.impl.*Impl.*(..)) || execution(public * com.iflytek.credit.platform.*.controller.*Controller.*(..))") public void pointCut() { } @Before("pointCut()") public void boBefore(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); logger.info("Method Name : [" + methodName + "] ---> AOP before "); } @After("pointCut()") public void doAfter(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); logger.info("Method Name : [" + methodName + "] ---> AOP after "); } @AfterReturning(pointcut = "pointCut()",returning = "result") public void afterReturn(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); logger.info("Method Name : [" + methodName + "] ---> AOP after return ,and result is : " + result.toString()); } @AfterThrowing(pointcut = "pointCut()",throwing = "throwable") public void afterThrowing(JoinPoint joinPoint, Throwable throwable) { String methodName = joinPoint.getSignature().getName(); logger.info("Method Name : [" + methodName + "] ---> AOP after throwing ,and throwable message is : " + throwable.getMessage()); } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); try { logger.info("Method Name : [" + methodName + "] ---> AOP around start"); long startTimeMillis = System.currentTimeMillis(); //調用 proceed() 方法才會真正的執行實際被代理的方法 Object result = joinPoint.proceed(); long execTimeMillis = System.currentTimeMillis() - startTimeMillis; logger.info("Method Name : [" + methodName + "] ---> AOP method exec time millis : " + execTimeMillis); logger.info("Method Name : [" + methodName + "] ---> AOP around end , and result is : " + result.toString()); return result; } catch (Throwable te) { logger.error(te.getMessage(),te); throw new RuntimeException(te.getMessage()); } } }
首先,需要創建一個類,然後在類名上加上兩個註解
@Component@Aspect
br/>@Aspect
類裏面每個方法的註解含義如下:
@Pointcut 用於定義切面的匹配規則,如果想要同事匹配多個的話,可以使用 || 把兩個規則連接起來,具體可以參照上面的代碼
@Before 目標方法執行前調用
@After 目標方法執行後調用
@AfterReturning 目標方法執行後調用,可以拿到返回結果,執行順序在 @After 之後
@AfterThrowing 目標方法執行異常時調用
@Around 調用實際的目標方法,可以在目標方法調用前做一些操作,也可以在目標方法調用後做一些操作。使用場景有:事物管理、權限控制,日誌打印、性能分析等等
需要註意的是,這些方法的執行順序:
執行目標方法前: 先進入 around ,再進入 before?
目標方法執行完成後: 先進入 around ,再進入 after ,最後進入 afterreturning?
實際的日誌信息如下,可以看出各個方法的執行順序:
?
另外,使用spring aop 需要在spring的配置文件加上以下這行配置,以開啟aop :
<aop:aspectj-autoproxy/>
同時,maven中需要加入依賴的jar包:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
總結一下,Spring AOP 其實就是使用動態代理來對切面層進行統一的處理,動態代理的方式有:JDK動態代理和 cglib 動態代理,JDK動態代理基於接口實現, cglib 動態代理基於子類實現。spring默認使用的是JDK動態代理,如果沒有接口,spring會自動的使用cglib動態代理。
如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群裏有阿裏大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家
Spring AOP 切面編程記錄日誌和接口執行時間