一、场景
假设我有2个服务:xxx-common 和 xxx-auth ,3个异常处理器。
目录结构如下:
xxx-common 公共类存放的jar包
自定义的 ApiExceptionHandler 类 有2个异常处理器,分别是:
① ApiException.class 和
② Exception.class
xxx-auth Shiro授权认证的jar包
自定义的 AuthorizationExceptionHandler 类 只有1个异常处理器:
③ AuthorizationException.class
二、问题
那么,在我A服务引入这两个包的同时,如果我报的是 AuthorizationException 异常,有可能会先走 xxx-common 包下的
ApiExceptionHandler 类 中的 ② Exception.class 异常处理器,这并不是我想要的结果。
三、解决办法
通过源码可以知道Spring的异常处理器是根据异常处理器被加载的顺序来顺序执行,
比如:A->B->C ,那么如果B符合抛出异常的条件,就会直接抛出,然而我们真正需要被执行的C可能就执行不到了。
此时,可以通过 @Order 注解来指定实体Bean被加载到Spring容器的顺序,注解中的值越小越优先加载。
@Order(1)//指定该实体bean被加载的顺序,注解中的值越小越优先被加载注入。
@RestControllerAdvice
public class AuthorizationExceptionHandler {
@ExceptionHandler(AuthorizationException.class)
public Code handleAuthorizationException(AuthorizationException e) {
log.error("没有权限的异常信息:", e);
return Code.NOT_PERMISSION.setErrCode(new Code().setMsg(e.getMessage()));
}
}
四、结论
其实,多个服务间多个自定义的ExceptionHandler类的执行顺序就是被Spring加载到容器中Bean加载顺序。
五、另外
在同一个自定义的ExceptionHandler类,定义多个异常处理器,他们的加载顺序如何决定?
结论:是由 ExceptionHandlerMethodResolver 通过递归查找调用链,内部自己判断决定的。调用链越小,执行度越高。
详情请看此链接:(转载)https://juejin.im/post/5d022d50f265da1bb564f374