Uniform exception handling is often encountered in project development. There is a solution in springMVC to use ExceptionHandler. So for example,
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler({IllegalArgumentException.class})
@ResponseBody
public Result handleIllegalArgumentException(IllegalArgumentException e) {
logger.error(e.getLocalizedMessage(), e);
return Result.fail(e.getMessage());
}
@ExceptionHandler({RuntimeException.class})
@ResponseBody
public Result handleRuntimeException(RuntimeException e) {
logger.error(e.getLocalizedMessage(), e);
returnResult.failure(); }}Copy the code
In this code, we can see that there are two exception-handling functions that handle IllegalArgumentException and RuntimeException, but on second thought, one question arises: IllegalArgumentException is a subclass of RuntimeException. Who will handle IllegalArgumentException? At first, I saw some answers on the Internet, and I could set Order, but after a simple test, I found that Order did not work. Although there is speculation in mind, but still hope to be able to find real proof of the idea, so they tried to find this piece of source code.
The source code interpretation
The call stack
After debugging step by step, the call stack is found as follows:
The core code
Decide the choice which is the core of ExceptionHandler code for ExceptionHandlerMethodResolver getMappedMethod method. The code is as follows:
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
List<Class<? extends Throwable>> matches = new ArrayList<Class<? extends Throwable>>();
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
if(mappedException.isAssignableFrom(exceptionType)) { matches.add(mappedException); }}if(! matches.isEmpty()) { Collections.sort(matches,new ExceptionDepthComparator(exceptionType));
return this.mappedMethods.get(matches.get(0));
}
else {
return null; }}Copy the code
This first finds all exceptionHandlers that can match the exception, and then sorts them, taking the one with the least depth (that is, the one with the highest degree of match).
As for the depth comparator algorithm shown below, it does a simple recursion, constantly judging whether the parent exception is the target exception to obtain the final depth.
conclusion
The source code is not long, we can easily find the answer we want — the order of ExceptionHandler is determined by the exception match, and there is no other way to specify the order (which is not necessary).