为什么要自定义异常
背景
我们在阅读各类源码时,会注意到几乎各个功能包中,都包含有自定义的异常;那有没有想过,JDK的源码中,已经定义了各种异常体系,为啥后续的一些依赖Jar包中,还要自定义异常呢?
下面摘取源码中的一些自定义异常:
- Mybatis的binding包下的绑定异常BindingException(它继承了PersistenceException,然后提供了一些构造方法)
- Mybatis的Cache包下的缓存异常CacheException(它继承了PersistenceException,然后提供了一些构造方法)
- Mybatis的dataSource包下的数据源异常DataSourceException
基于以上Mybatis的源码中,定义的自定义异常,我们发现它针对各种不同的业务场景,定义了不同的异常类,而不是不加区分的使用原生的RuntimeException或者通用父类异常PersistenceException。从上述源码中,可以窥见自定义异常是必要的,那么为什么要自定义异常呢?
为什么需要自定义异常
-
异常分类
自定义异常允许你根据错误的类型进行分类。
例如上述Mybatis的持久化异常,你可以创建一个基础异常类PersistenceException,然后为不同场景类型的持久化错误创建子类BindingException、CacheException、DataSourceException等。
这样通过不同的子类异常,我们就可以更方便的区分不同的异常场景。
-
异常处理策略
自定义异常可以与特定的异常处理策略关联。
例如,针对异常的不同情况,可能存在不的处理策略:有些立即重试、有些延时重试,有些只记录日志、而其他异常可能需要通知用户。
所以自定义不同的异常类型,有助于我们更好的实施不同的处理策略。
-
更明确的信息
自定义异常,可以传递更加明确的异常信息。还是拿上面的异常来说,假如Mybatis中,上述绑定、缓存、数据源异常,我们统一使用父类的PersistenceException,那它显然没有对应的子类传递的异常信息明确。
同时自定义异常,我们也可以对原有异常信息,进行扩展丰富,比如如下异常的构造方法中,我们可以在原有的message上追加一些更详细的内容:比如添加前缀信息等(xxx数据源异常:)
也可以在抛出异常时,根据构造方法,自定义异常信息。
-
业务流程控制
结合上述几点,使用自定义异常,可以实现更细粒度的业务流程控制。
使用特定的自定义异常,可以减少在 try-catch 块中误用通用异常的风险。比如在catch捕获Exception 或 PersistenceException 或 BindingException,将支持将异常处理逻辑粒度变得更加明确。