spring aop中使用@Pointcut注解抽取可重用的切入点表达式

针对同一个切入点,如果有多个通知方法将切入时,通常我们需要标注多个注解,每个注解需要使用切入点表达式,告诉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()方法上的切入表达式即可。

发布了98 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41885819/article/details/104772007
今日推荐