針對同一個切入點,如果有多個通知方法將切入時,通常我們需要標註多個註解,每個註解需要使用切入點表達式,告訴spring,當前通知方法在何時執行。當一個切入點需要更改時,就需要同時更改多個。爲了避免這種麻煩,提高切入點表達式的可重用性,以此衍生出的@Pointcut,可以用於標誌一個切入點。
示例:
如前文中的切面類StudentServiceLogger
,針對StudentServiceImpl
類的所有方法都切入了四個通知,如果某天,我想改成只對其中一個方法切入時,就需要來修改這四個註解的切入點表達式。
@Aspect
@Component
public class StudentServiceLogger {
@Before("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )")
public void doBefore(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法執行前...");
System.out.println("參數爲:"+ Arrays.asList(args));
}
@After("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )")
public void doAfter(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法執行後...");
}
@AfterReturning(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )" , returning = "returning")
public void doReturn(JoinPoint joinPoint,Object returning){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法返回,返回值爲:"+returning);
}
@AfterThrowing(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )",throwing = "ex")
public void doThrow(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法異常,異常信息爲:"+ex.getMessage());
}
}
使用@Pointcut的示例
上面的示例,完全等價於下面這個切面類。
@Aspect
@Component
public class StudentServiceLogger {
@Pointcut("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )")
public void basePointCut(){}
@Before("basePointCut()")
public void doBefore(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法執行前...");
System.out.println("參數爲:"+ Arrays.asList(args));
}
@After("basePointCut()")
public void doAfter(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法執行後...");
}
@AfterReturning(value = "basePointCut()" , returning = "returning")
public void doReturn(JoinPoint joinPoint,Object returning){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法返回,返回值爲:"+returning);
}
@AfterThrowing(value = "basePointCut()",throwing = "ex")
public void doThrow(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName+"方法異常,異常信息爲:"+ex.getMessage());
}
}
我們聲明瞭一個basePointCut()
空方法,並且返回值需要爲void,爲該方法標註上@Pointcut
註解,鍵入之前我們那四個通知方法的公用切入點表達式。然後,將後續的所有使用到之前那個切入表達式的地方,替換成basePointCut()
這個方法名,以此指向同一個的切入點表達式。後續的所有變動,我都可以只更改basePointCut()
方法上的切入表達式即可。