JSR 303 Bean验证 - 为什么在getter而不是setter?

时间:2011-06-08 18:52:48

标签: bean-validation getter

我不明白为什么JSR 303(bean验证)是针对getter方法而不是setter的?将它放在setter方法下是不合逻辑的,因为那是进入字段的入口点,应该在此之前检查验证?

4 个答案:

答案 0 :(得分:27)

注释getter并不意味着在调用getter时执行验证。它仅用于标识约束应适用的属性。

将约束放在(通常是公共的)getter而不是(通常是私有的)字段上的一大优点是约束是该类型的公共API的一部分。它们甚至会被添加到生成的JavaDoc中。类型的用户知道哪种约束适用于它而不考虑其内部实现。

注释getter的另一个好处是可以将约束放在基类或接口上的方法中,也可以应用于任何子类型/实现。

答案 1 :(得分:6)

这是一个非常好的问题和我从未注意过的事情。但我想我知道答案(也是我自己从未得到过这个问题的原因)。

如果您正在考虑这一点,从注释的角度来看,注释定义了验证将发生的位置,然后将其置于getter上是没有意义的。 (为什么不在存储值本身时进行验证..)。但这不是它的工作原理......

程序员需要告诉验证框架,需要验证哪些属性。因此,您可以将注释直接放在属性(我更喜欢)上,也可以将其放在getter上。它们都表示读操作。框架需要读取您的类的所有属性,这些属性必须经过验证。所以在这种情况下,穿上setter根本就没有意义。要理解的关键是透视......

我希望这是有道理的。

答案 2 :(得分:5)

考虑以下代码:

public class BeanValidation {

    private int nameSetCount = 0;
    private int nameGetCount = 0;
    private String name;

    public String getName() {
        this.nameGetCount++;
        return name;
    }

    public void setName(String name) {
        this.nameSetCount++;
        this.name = name;
    }

}

将注释放在private String name;

注释只需查看字段即可轻松识别字段。

将注释放在public String getName()

注释只需查看返回的字段即可轻松识别字段。

将注释放在public void setName(String name)

注释无法识别字段查看已修改字段,因为可以有多个。

答案 3 :(得分:0)

以这种方式调用Bean验证是有原因的。它应用于初始化的bean。因此,首先,使用您拥有的所有内容对其进行初始化,然后将其传递(或显式传递)到Bean Validation实现,该实现将在访问字段时依赖于验证批注。 如果是Spring MVC,则验证处理始于:

result = execVal.validateParameters(
                invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
MethodValidationInterceptor

。从这里开始,它传递给验证实现,在大多数情况下为Hibernate。 invocation.getArguments()将包含所有已使用给定值初始化的方法参数,而不考虑验证注释。