在上篇文章中學習了Spring AOP,并學習了前置通知和后置通知。地址為:http://m.survivalescaperooms.com/dreamfree/p/4095858.html
在本文中,將繼續上篇的學習,繼續了解返回通知、異常通知和環繞通知。具體的含義詳見代碼注釋
1 package com.yl.spring.aop; 2 3 import java.util.Arrays; 4 5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.ProceedingJoinPoint; 7 import org.aspectj.lang.annotation.After; 8 import org.aspectj.lang.annotation.AfterReturning; 9 import org.aspectj.lang.annotation.AfterThrowing;10 import org.aspectj.lang.annotation.Around;11 import org.aspectj.lang.annotation.Aspect;12 import org.aspectj.lang.annotation.Before;13 import org.springframework.stereotype.Component;14 15 @Component16 @Aspect17 public class LoggingAspect {18 19 /**20 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一個實現類的每一個方法開始之前執行一段代碼21 */22 @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")23 public void beforeMethod(JoinPoint joinPoint) {24 String methodName = joinPoint.getSignature().getName();25 Object[] args = joinPoint.getArgs();26 System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));27 }28 29 /**30 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一個實現類的每一個方法執行之后執行一段代碼31 * 無論該方法是否出現異常32 */33 @After("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")34 public void afterMethod(JoinPoint joinPoint) {35 String methodName = joinPoint.getSignature().getName();36 Object[] args = joinPoint.getArgs();37 System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));38 }39 40 /**41 * 方法正常結束后執行的代碼42 * 返回通知是可以訪問到方法的返回值的43 */44 @AfterReturning(value="execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))", returning="result")45 public void afterReturning(JoinPoint joinPoint, Object result) {46 String methodName = joinPoint.getSignature().getName();47 System.out.println("The method " + methodName + " return with " + result);48 }49 50 /**51 * 在方法出現異常時會執行的代碼52 * 可以訪問到異常對象,可以指定在出現特定異常時在執行通知代碼53 */54 @AfterThrowing(value="execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))", throwing="ex")55 public void afterThrowing(JoinPoint joinPoint, Exception ex) {56 String methodName = joinPoint.getSignature().getName();57 System.out.println("The method " + methodName + " occurs exception: " + ex);58 }59 60 /**61 * 環繞通知需要攜帶ProceedingJoinPoint類型的參數62 * 環繞通知類似于動態代理的全過程:ProceedingJoinPoint類型的參數可以決定是否執行目標方法。63 * 而且環繞通知必須有返回值,返回值即為目標方法的返回值64 */65 @Around("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")66 public Object aroundMethod(ProceedingJoinPoint pjd) {67 Object result = null;68 String methodName = pjd.getSignature().getName();69 //執行目標方法70 try {71 //前置通知72 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));73 result = pjd.proceed();74 //返回通知75 System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));76 } catch (Throwable e) {77 //異常通知78 System.out.println("The method " + methodName + " occurs expection : " + e);79 throw new RuntimeException(e);80 }81 //后置通知82 System.out.println("The method " + methodName + " ends");83 return result;84 }85 86 }
切面的優先級
為項目增加一個新的切面類,負責驗證功能,則需要指定切面執行的順序。即切面的優先級。具體方法是給切面類增加@Order注解,并指定具體的數字,值越小優先級越高
1 package com.yl.spring.aop; 2 3 import java.util.Arrays; 4 5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.annotation.Aspect; 7 import org.aspectj.lang.annotation.Before; 8 import org.springframework.core.annotation.Order; 9 import org.springframework.stereotype.Component;10 11 /**12 * 可以使用@Order注解指定切面的優先級,值越小優先級越高13 * @author yul14 *15 */16 @Order(2)17 @Component18 @Aspect19 public class ValidationAspect {20 21 @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")22 public void vlidateArgs(JoinPoint joinPoint) {23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));24 }25 }切點表達式的重用:
在LoggingAspect類中,切點的表達式可以先定義,在使用。
1 package com.yl.spring.aop; 2 3 import java.util.Arrays; 4 5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.ProceedingJoinPoint; 7 import org.aspectj.lang.annotation.After; 8 import org.aspectj.lang.annotation.AfterReturning; 9 import org.aspectj.lang.annotation.AfterThrowing;10 import org.aspectj.lang.annotation.Around;11 import org.aspectj.lang.annotation.Aspect;12 import org.aspectj.lang.annotation.Before;13 import org.aspectj.lang.annotation.Pointcut;14 import org.springframework.core.annotation.Order;15 import org.springframework.stereotype.Component;16 @Order(1)17 @Component18 @Aspect19 public class LoggingAspect {20 21 /**22 * 定義一個方法,用于聲明切入點表達式。一般的,該方法中再不需要添加其他的代碼23 * 使用@Pointcut 來聲明切入點表達式24 * 后面的其他通知直接使用方法名直接引用方法名即可25 */26 @Pointcut("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")27 public void declareJoinPointExpression() {28 29 }30 31 /**32 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一個實現類的每一個方法開始之前執行一段代碼33 */34 @Before("declareJoinPointExpression()")35 public void beforeMethod(JoinPoint joinPoint) {36 String methodName = joinPoint.getSignature().getName();37 Object[] args = joinPoint.getArgs();38 System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));39 }40 41 /**42 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一個實現類的每一個方法執行之后執行一段代碼43 * 無論該方法是否出現異常44 */45 @After("declareJoinPointExpression()")46 public void afterMethod(JoinPoint joinPoint) {47 String methodName = joinPoint.getSignature().getName();48 Object[] args = joinPoint.getArgs();49 System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));50 }51 52 /**53 * 方法正常結束后執行的代碼54 * 返回通知是可以訪問到方法的返回值的55 */56 @AfterReturning(value="declareJoinPointExpression()", returning="result")57 public void afterReturning(JoinPoint joinPoint, Object result) {58 String methodName = joinPoint.getSignature().getName();59 System.out.println("The method " + methodName + " return with " + result);60 }61 62 /**63 * 在方法出現異常時會執行的代碼64 * 可以訪問到異常對象,可以指定在出現特定異常時在執行通知代碼65 */66 @AfterThrowing(value="declareJoinPointExpression()", throwing="ex")67 public void afterThrowing(JoinPoint joinPoint, Exception ex) {68 String methodName = joinPoint.getSignature().getName();69 System.out.println("The method " + methodName + " occurs exception: " + ex);70 }71 72 /**73 * 環繞通知需要攜帶ProceedingJoinPoint類型的參數74 * 環繞通知類似于動態代理的全過程:ProceedingJoinPoint類型的參數可以決定是否執行目標方法。75 * 而且環繞通知必須有返回值,返回值即為目標方法的返回值76 */77 @Around("declareJoinPointExpression()")78 public Object aroundMethod(ProceedingJoinPoint pjd) {79 Object result = null;80 String methodName = pjd.getSignature().getName();81 //執行目標方法82 try {83 //前置通知84 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));85 result = pjd.proceed();86 //返回通知87 System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));88 } catch (Throwable e) {89 //異常通知90 System.out.println("The method " + methodName + " occurs expection : " + e);91 throw new RuntimeException(e);92 }93 //后置通知94 System.out.println("The method " + methodName + " ends");95 return result;96 }97 98 }當處于不同的類,甚至不同的包時,可以使用包名.類名.方法名
具體代碼如下:
1 package com.yl.spring.aop; 2 3 import java.util.Arrays; 4 5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.annotation.Aspect; 7 import org.aspectj.lang.annotation.Before; 8 import org.springframework.core.annotation.Order; 9 import org.springframework.stereotype.Component;10 11 /**12 * 可以使用@Order注解指定切面的優先級,值越小優先級越高13 * @author yul14 *15 */16 @Order(2)17 @Component18 @Aspect19 public class ValidationAspect {20 21 @Before("com.yl.spring.aop.LoggingAspect.declareJoinPointExpression()")22 public void vlidateArgs(JoinPoint joinPoint) {23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));24 }25 }新聞熱點
疑難解答