AOP是在處理Cross-cutting concerns,將某段代碼(日誌)動態切入(不把日誌程式hardcode到業務邏輯方法中)到指定方法(加減乘除)的指定位置進行運行。
昨天我們學到了AOP中Advice的執行順序、透過Advice方法給定參數JointPoint可以取得方法的相關訊息,在AfterReturning、AfterThrowing可在方法給定參數與在pointcut expression來接收回傳值與Exception
今日我們將探討AOP的Around advice與如何共用pointcut expression
@Aspect
@Component
public class LogUtils {
@Pointcut(value = "execution(public int com.swj.MyCalculator.*(..))")
public void pointCutExpressionShare(){}
@Before("pointCutExpressionShare()")
public static void logStart(JoinPoint jointPoint){
//取得方法名稱,與parameter
System.out.println("["+jointPoint.getSignature().getName()+"] method start,parameter:"+Arrays.asList(jointPoint.getArgs()));
}
@AfterReturning(value = "pointCutExpressionShare()",returning = "result")
public static void logReturn(JoinPoint joinPoint, Object result){
System.out.println("["+joinPoint.getSignature().getName()+"] method completed,result is "+result);
}
@After("pointCutExpressionShare()")
public static void logEnd(JoinPoint joinPoint){
System.out.println("["+joinPoint.getSignature().getName()+"] method end");
}
@AfterThrowing(value = "pointCutExpressionShare()",throwing = "exception")
public static void logException(JoinPoint joinPoint,Exception exception){
System.out.println("["+joinPoint.getSignature().getName()+"] method throws exception:"+exception);
}
}
Result
自定義的Advice方法,包含前面4種的Advice
@Aspect
@Component
public class LogUtils {
@Around("pointCutExpressionShare()")
public Object aroundAdvice(ProceedingJoinPoint pjp){
Object[] params = pjp.getArgs();
String methodName = pjp.getSignature().getName();
Object proceed =null;
try {
System.out.println("["+methodName+"][Around Advice] Before");
//目標方法invoke
proceed = pjp.proceed(params);
System.out.println("["+methodName+"][Around Advice] AfterReturning");
}catch (Throwable e){
System.out.println("["+methodName+"][Around Advice] AfterThrowing");
}finally {
System.out.println("["+methodName+"][Around Advice] After");
}
return proceed;
}
}
Result
Around_Before -> @Before -> target invoke -> Around_Returning/Around_Throwing -> Around_After -> @After -> AfterReturning/AfterThrowing
@AfterThrowing(value = "pointCutExpressionShare()",throwing = "exception")
public static void logException(JoinPoint joinPoint,Exception exception){
System.out.println("["+joinPoint.getSignature().getName()+"] method throws exception:"+exception);
}
@Around("pointCutExpressionShare()")
public Object aroundAdvice(ProceedingJoinPoint pjp){
Object[] params = pjp.getArgs();
String methodName = pjp.getSignature().getName();
Object proceed =null;
try {
//@Before
System.out.println("["+methodName+"][Around Advice] Before");
//目標方法invoke
proceed = pjp.proceed(params);
//AfterReturning
System.out.println("["+methodName+"][Around Advice] AfterReturning");
}catch (Throwable e){
//AfterThrowing
System.out.println("["+methodName+"][Around Advice] AfterThrowing");
throw new RuntimeException(e);
}finally {
//After
System.out.println("["+methodName+"][Around Advice] After");
}
return proceed;
}
Result