Сигнатура класса определяет тип данных, с которым ассоциируется ограничение. В листинге 3.8 URLValidator реализован для типа String (ConstraintValidator
Реализация ограничения считается управляемым компонентом. Это означает, что с ней вы можете использовать все сервисы, доступные для обработки управляемых компонентов — в частности, внедрение любого вспомогательного класса, EJB или даже EntityManager (подробнее об этом — в следующих главах). Вы также можете перехватывать или декорировать методы initialize и isValid и даже задействовать управление жизненным циклом (@PostConstruct и @PreDestroy).
Иногда полезно применять одинаковое ограничение к одной и той же цели, используя при этом разные свойства или группы (подробнее об этом ниже). Распространенный пример такого рода — ограничение @Pattern, проверяющее соответствие целевой сущности определенному регулярному выражению. В листинге 3.9 показано, как применить два регулярных выражения к одному и тому же атрибуту. Множественные ограничения используют оператор AND. Это означает, что для валидности атрибута orderId необходимо, чтобы он удовлетворял двум регулярным выражениям.
public class Order {
··@Pattern.List({
······@Pattern(regexp = "[C,D,M][A-Z][0–9]*"),
······@Pattern(regexp = ".[A-Z].*?")
··})
··private String orderId;
··private Date creationDate;
··private Double totalAmount;
··private Date paymentDate;
··private Date deliveryDate;
··private List
··// Конструкторы, геттеры, сеттеры
}
Чтобы иметь возможность несколько раз применить одно и то же ограничение к данной цели, ограничивающая аннотация должна определить массив на основе самой себя. При валидации компонентов такие массивы ограничений обрабатываются по-особому: каждый элемент массива интерпретируется как обычное ограничение. В листинге 3.10 показана ограничивающая аннотация @Pattern, определяющая внутренний интерфейс (произвольно названный List) с элементом Pattern[]. Внутренний интерфейс должен иметь правило хранения RUNTIME и использовать в качестве исходного ограничения один и тот же набор целей (в данном случае METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER).
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Constraint(validatedBy = PatternValidator.class)
public @interface Pattern {
··String regexp();