Spring 返回通知 异常通知 环绕通知

2020-03-19  本文已影响0人  BlueSkyBlue

返回通知

在方法正常返回结果后的通知。返回通知可以访问到方法的返回值。

示例(附带返回结果的返回通知):

@AfterReturning(value = "execution(public int com.spring.impl.ArithmeticCalculator.*(..))",
                returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result){
    String methodName = joinPoint.getSignature().getName();
    System.out.println("The method " + methodName + " ends with " + result);
 }

异常通知

方法出现异常后返回的通知。可以访问异常的对象,并且可以指定出出现特定异常时在执行通知的代码。

示例(附带返回的异常):

@AfterThrowing(value = "execution(public int com.spring.impl.ArithmeticCalculator.*(..))",
                throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex){
    String methodName = joinPoint.getSignature().getName();
    System.out.println("The method " + methodName + " occurs exception " + ex);
}

环绕通知

环绕通知需要携带ProceedingJoinPoint类型的参数。
环绕通知类似于动态代理的全过程。ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
环绕通知必须有返回值。返回值必为目标方法的返回值。

示例:

@Around("execution(public int com.spring.impl.ArithmeticCalculator.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjd){

    String methodName = pjd.getSignature().getName();
    Object result = null;
    try {
        System.out.println("The method name " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
        result = pjd.proceed();
        System.out.println("The method name " + methodName + " ends with " + result);
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    return result;
}

Spring切面的优先级

如果此时我们新增加一个切面

@Aspect
@Component
public class ValidationAspect {
    @Before("execution(public int com.spring.impl.ArithmeticCalculator.*(..))")
    public void validateArgs(JoinPoint joinPoint){
        System.out.println("Validate " + Arrays.asList(joinPoint.getArgs()));
    }
}

它的目标目标对象和上述的一样。这样问题来了,到底先执行那一个呢?

可以使用@Order指定切面的优先级,值越小切面的优先级越高。

示例:
ValidationAspect类

@Order(1)
@Aspect
@Component
public class ValidationAspect {
    @Before("execution(public int com.spring.impl.ArithmeticCalculator.*(..))")
    public void validateArgs(JoinPoint joinPoint){
        System.out.println("Validate " + Arrays.asList(joinPoint.getArgs()));
    }
}

LoggingAspect类

@Order(2)
@Component
@Aspect
public class LoggingAspect {
    @Around("execution(public int com.spring.impl.ArithmeticCalculator.*(..))")
    public Object aroundMethod(ProceedingJoinPoint pjd){

        String methodName = pjd.getSignature().getName();
        Object result = null;
        try {
            System.out.println("The method name " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
            result = pjd.proceed();
            System.out.println("The method name " + methodName + " ends with " + result);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }
}

由于ValidationAspect指定了较高的优先级,所以先执行ValidationAspect中的切面。

Spring重用切入点表达式

定义一个方法用于定义切入点表达式。一般地,该方法中不需要添入其它代码。

使用@PointCut来声明切入点表达式。后面的通知直接使用方法名来引用当前的切入点表达式。

定义切入点:

@Pointcut("execution(public int com.spring.impl.ArithmeticCalculator.*(..))")
public void declareJointPointExpression(){

}

引用切入点:

@Around("declareJointPointExpression()")
public Object aroundMethod(ProceedingJoinPoint pjd){
    String methodName = pjd.getSignature().getName();
    Object result = null;
    try {
        System.out.println("The method name " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
        result = pjd.proceed();
        System.out.println("The method name " + methodName + " ends with " + result);
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    return result;
}
上一篇下一篇

猜你喜欢

热点阅读