JSR 303 Bean 验证 - 为啥使用 getter 而不是 setter?
Posted
技术标签:
【中文标题】JSR 303 Bean 验证 - 为啥使用 getter 而不是 setter?【英文标题】:JSR 303 Bean Validation - Why on getter and not setter?JSR 303 Bean 验证 - 为什么使用 getter 而不是 setter? 【发布时间】:2011-09-11 03:23:30 【问题描述】:我不明白为什么 JSR 303(bean 验证)适用于 getter 方法而不适用于 setter?将它放在 setter 方法下不是更合乎逻辑吗,因为这是一个字段的入口点,并且应该在此之前检查验证?
【问题讨论】:
我不明白您为什么要将约束放在吸气剂而不是字段本身上。将它放在字段本身上不是更合乎逻辑吗,因为那是唯一的字段本身? @BalusC 是的!我同意你的看法。所以问题是如果我对那个字段进行验证,我是否还需要在那个字段 getter 方法上添加注释?如果没有,为什么getter方法根本没有注释? 你绝对不应该把它放在两个地方。根据 Hibernate 文档,它将导致该字段被验证两次。 同样的问题,放在 setter 或 field 本身更直观。一些库在错误的地方使用它,现在由于验证异常我无法加载这些库 【参考方案1】:这是一个非常好的问题,而且我从未关注过。但我想我知道答案(以及为什么我自己从来没有收到过这个问题)。
如果你正在看这个,从这个角度来看,注释定义了验证将发生的位置,那么将它放在 getter 上是没有意义的。 (为什么在存储值本身时不进行验证..)。但这不是它的工作原理......
程序员需要告诉验证框架,哪些属性需要验证。因此,您可以将注释直接放在属性上(我更喜欢),也可以将其放在 getter 上。它们都表示读操作。框架需要读取您的类的所有属性,这些属性必须经过验证。所以在这种情况下,装上setter一点意义都没有。理解的关键是视角……
我希望这是有道理的。
【讨论】:
是的,如果你这样看它是没有意义的。我不认为将您的注释定位在 getter 上,而是在 getter 上执行验证。我们只是将该属性标记为框架需要验证的内容。 我明白你想说什么。据我了解 JSF 生命周期,如果在流程验证阶段出现验证错误,则会重新显示相同的页面。不应该调用 setter 方法来进行验证吗?仅在页面呈现阶段调用 getter 方法。为什么要在页面渲染阶段进行验证?在我看来,在这个阶段进行验证是没有意义的,因为......现在一切都很好,因此所述页面被渲染以供显示。 这是因为有些情况下没有setter方法。设置器不会包含在只读属性中。【参考方案2】:注释 getter 并不意味着在调用 getter 时执行验证。它仅用于标识应应用约束的属性。
将约束放在(通常是公共的)getter 上而不是放在(通常是私有的)字段上的最大优势在于,约束是该类型公共 API 的一部分。它们甚至会被添加到生成的 JavaDoc 中。一个类型的用户知道哪些约束适用于它,而无需查看其内部实现。
注释 getter 的另一个优点是可以将约束放在基类或接口的方法上,也可以应用于任何子类型/实现。
【讨论】:
如果是这种情况,如果对公共 setter 方法施加约束,我看不到任何问题。与您的答案相同的结果 我认为使用 getter 而不是 setter 方法的一个优点是,这允许拥有不存在 setter 的不可变属性,同时获得属性级别(相对于字段级别)约束的优势,如上所述。 @yapkm01 请看我的回答。 setter 方法有问题。您不能总是使用公共 setter 方法预测正确的字段。【参考方案3】:考虑这段代码:
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)
上添加注释
注解无法识别字段查看修改后的字段,因为可能有多个。
【讨论】:
反射不查看方法实现,它查看 getter/setter 的名称并将其与字段匹配【参考方案4】:Bean Validation 以这种方式调用是有原因的。它应用于一个初始化的bean。所以,首先,你用你所有的东西初始化它,然后你把它(或者它被显式地传递)传递给 Bean Validation 实现,它在访问字段时将依赖于验证注解。 如果 Spring MVC 验证处理开始于:
result = execVal.validateParameters(
invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
在MethodValidationInterceptor
内。从这里开始,它被传递给验证实现,在大多数情况下是 Hibernate。
invocation.getArguments()
将包含所有已使用给定值初始化的方法参数,无论验证注释如何。
【讨论】:
以上是关于JSR 303 Bean 验证 - 为啥使用 getter 而不是 setter?的主要内容,如果未能解决你的问题,请参考以下文章
JSR 303 Bean 验证 + Javascript 客户端验证
Wildfly:ExceptionMapper 未通过 RestEasy JSR-303 Bean 验证触发