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;
}