Assert类的使用思考
Spring 框架的 Assert 类主要用于简化方法的参数校验。
在介绍 Spring 框架的 Assert 类之前,我们先来研究下程序错误处理的方式,因为参数校验错误也是程序错误的一种。
1. 程序错误处理
1.1. 方式
当程序出现错误时,采用返回值的方式将错误信息传递给方法调用者。
当程序出现错误时,采用抛异常的方式将错误信息传递给方法调用者。
1.2. 对比
错误处理方式 | 优点 | 缺点 |
---|---|---|
返回错误 | 1、没有额外的性能开销; | 1、错误处理跨越多个调用层次时,需要处于中间层次的方法手动转发错误信息给上层; 2、可能出现处于中间层次的方法忘记处理错误而引发的bug; 3、所有方法的返回值必须包含错误信息; |
抛出异常 | 1、记录异常调用栈; 2、异常可以携带任意丰富的信息; 3、异常中立的方法无需涉及到异常的转发; 4、方法的返回值不需要包含异常信息; | 1、抛异常的方式会有额外的性能开销,不过开销也不算大; |
1.3. 选择的参考因素
对于错误处理方式的选择,可以看情况进行选择,而不是只能二选一。
我觉得,可以把错误产生到错误处理的方法调用层数作为一个参考因素,如果错误处理跨越多个层次调用时,则建议采用抛出异常的方式,错误处理跨越层次不多时,则两种方式都可以,而采用返回错误的方式可以节省额外的性能开销。
在Spring框架中,参数校验不通过时,采用的是抛出异常的方式,不过为了简化参数校验的代码,Spring框架封装了Assert类,该类包含多个对参数校验的方法,比如 notNull、isNull、isTrue、hasText、state 等。
2. Assert类
2.1. Assert类注释
帮助验证参数的断言实用程序类。
有助于在运行时尽早并清楚地识别程序员错误。
例如,如果公共方法的契约声明它不允许null参数,则可以使用Assert来验证该契约。 这样做清楚地表明发生了违反合同并保护了类的不变量。
通常用于验证方法参数而不是配置属性,以检查通常是程序员错误而不是配置错误的情况。 与配置初始化代码相比,在这些方法中回退到默认值通常没有意义。
这个类类似于 JUnit 的断言库。 如果认为参数值无效,则会IllegalArgumentException (通常)。 例如:
Assert.notNull(clazz, “The class must not be null”);
Assert.isTrue(i > 0, “The value must be greater than zero”);
主要供框架内部使用;要获得更全面的断言实用程序套件,请考虑Apache Commons Lang 中的 org.apache.commons.lang3.Validate 、Google Guava 的Preconditions 或类似的第三方库。
2.2. 总结
Assert类提供对方法入参进行校验的功能,当入参校验不通过时会抛出异常(IllegalArgumentException、IllegalStateException),它出现的目的是为了
简化方法入参校验的判断,可以写出更加优雅的代码,例如:
if(name == null) {
throw new IllegalArgumentException("name must not be null.");
}
Assert.notNull(name, "name must not be null.");
2.3. 思考
Assert 类被广泛应用于 Spring 框架,是否也适用于web应用开发?
我的结论是:当采用抛异常的方式处理参数校验错误,并且参数校验个数不多时,可以考虑使用 Assert 类进行参数校验。
如果参数校验的个数比较多,可以考虑采用 Hibernate Validator 框架进行参数校验,而且 Spring 框架已经集成 Hibernate Validator 框架提供了一套参数校验方法,可以采用编程式或注解式的方式进行参数校验。基于注解式的方式,Spring 框架也提供了两种处理方式,一种是抛异常 MethodArgumentNotValidException,另外一种是将参数校验结果封装到 BindingResult 对象,这两种方式分别对应着抛出异常和返回错误的错误处理方式,最后选择哪种方式可以由开发者自行决定。
参考资料
异常exception与error-code:https://blog.csdn.net/u014053368/article/details/22598233
一文弄懂spring validate:https://segmentfault.com/a/1190000038859664