1. 程式人生 > >Hibernate Validator 6.0.7.Final 之三(宣告方法約束)

Hibernate Validator 6.0.7.Final 之三(宣告方法約束)

本文要講解的是怎樣宣告方法約束。
首先,我們要明白什麼是方法約束:其實就是對方法的引數和返回值進行約束,這裡說的方法包括構造方法。下面這個例子就是方法約束,更準確地說,它是引數約束。

public class RentalStation {
    // 構造方法
    public RentalStation(@NotNull String name) {}

    // 普通方法
    public void rentCar(@NotNull Customer customer, @NotNull @Future Date startDate,
            @Min
(1) int durationInDays) {} private class Customer { } }

  我們可以把引數約束看做是一種前置條件,方法的呼叫者必須先滿足引數約束,該方法才能被成功呼叫;而返回值約束可以看做是一種後置條件,方法的返回值必須滿足這些約束。
  需要注意的是,引數約束只能用於例項方法。比如說,類中靜態方法就不能應用引數約束。
  有時候,我們可能不僅僅是對單個引數進行約束,而是需要對多個引數同時進行約束,也就是跨引數約束,這種情況也是支援的。
  可以拿跨引數約束和類級別的約束比較一下。相同點是二者都基於多個元素。不同的是,後者作用於類,約束物件是類的屬性;而前者作用於方法,約束物件是方法的引數。看下面這個例子:
這裡寫圖片描述


該方法有2個引數,第一代表乘客,第二個代表行李,我們使用跨引數約束LuggageCountMatchesPassengerCount來限制每個乘客不能攜帶超過兩件的行李。(具體怎麼實現不是本文要講的)
  從上面我們可以看出來,對單個引數進行約束的時候,我們的約束(註解)是寫在引數前邊的;而跨引數約束則是寫在方法簽名上面的。
  其實,返回值約束(文末有例子)也是寫在方法簽名上面的。那麼,我們怎麼區分一個約束是跨引數約束還是返回值約束呢?此時,需要為約束指定validationAppliesTo屬性。看例子:
這裡寫圖片描述
同時也可以看一下validation-api對ValidationTarget的定義:

public enum ValidationTarget {

    /**
     * (Returned) element annotated by the constraint.
     */
    ANNOTATED_ELEMENT,

    /**
     * Array of parameters of the annotated method or constructor (aka cross-parameter).
     */
    PARAMETERS
}

  承上,其實多數情況下,約束的應用目標是可以自動推斷出來的(此時可以省略validationAppliesTo屬性)。比如:

  1. 返回值是void但是有引數,此時自然是對引數進行約束;
  2. 返回值不是void但是沒有引數,此時自然是對返回值進行約束;

  但是為了程式碼的可讀性,還是建議加上validationAppliesTo屬性
  文章開頭看了引數約束的例子,結尾的時候看一個返回值約束的例子,比較一下。
這裡寫圖片描述