我不明白为什么JSR 303(bean验证)是针对getter方法而不是setter的?将它放在setter方法下是不合逻辑的,因为那是进入字段的入口点,应该在此之前检查验证?
答案 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()
将包含所有已使用给定值初始化的方法参数,而不考虑验证注释。