Can we handle exception like try-catch
construction with Spring AOP?
When some exception thrown and correspondent aspect contains two advices, with exception class and its superclass,
@AfterThrowing(pointcut = "bean(advisedService)", throwing = "e")
void afterThrowingException(RuntimeException e) {}
@AfterThrowing(pointcut = "bean(advisedService)", throwing = "e")
void afterThrowingException(Exception e) {}
they both are applying.
While in plain catch(…){}
we can achieve the desired result by ordering from subclass to superclass (from particular to general):
try {
advisedService.doSomething();
}
catch (RuntimeException e) {}
catch (Exception e) {}
and process handling ex of specific type just once✔️
GitHub //with demo test
The aspect behaves exactly as expected, the way you designed it. Try not to compare apples with pears. In an @AfterThrowing
advice, you cannot catch/handle exceptions, only do something on top of the exception being thrown, e.g. log them the way you do. Both of your advice methods will fire, because both pointcuts match. So far, so normal.
If you want different behaviour, just change the code. How about this?
@AfterThrowing(pointcut = "bean(advisedService)", throwing = "e")
void afterThrowingException(Exception e) {
System.out.printf(
"AdvisedServiceAspect %s exception: %s%n",
e instanceof RuntimeException ? "runtime" : "checked",
e.getClass().getSimpleName()
);
}
Or if you really want to handle exceptions and not just log them, use an @Around
advice (made-up example):
@Around("bean(advisedService)")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
try {
return joinPoint.proceed();
}
catch (RuntimeException e) {
System.out.println("Runtime exception caught, returning null");
return null;
}
catch (Exception e) {
throw new RuntimeException("Wrap checked exception in runtime exception", e);
}
// Do not handle Throwable, i.e. let it escalate
}