Backend Development 7 min read

Master Spring Bean Validation: From Basics to Custom Annotations

This guide explains how to configure and use Spring Bean Validation, demonstrates simple and method‑level validation, and shows how to create custom constraint annotations with full code examples for a Spring Boot 2.4.11 application.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Bean Validation: From Basics to Custom Annotations

Overview

Bean Validation provides a generic way to validate Java objects using constraint annotations and metadata. By annotating POJO fields with constraints such as

@NotNull

or

@Size

, the runtime enforces the rules.

<code>public class Person {
    @NotNull
    @Size(max = 64)
    private String name;

    @Min(0)
    private int age;
}</code>

Configuring a Bean Validation Provider

Spring integrates the Bean Validation API and allows the validator to be injected as a Spring bean. The typical configuration uses

LocalValidatorFactoryBean

:

<code>import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class AppConfig {

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }
}</code>

With this setup, the validator implementation (e.g., Hibernate Validator) is auto‑detected on the classpath.

Injecting the Validator

<code>@Service
public class PersonService {

    // Java EE validator
    @Resource
    private Validator validator;

    // Spring validator
    @Resource
    private org.springframework.validation.Validator springValidator;
}</code>

Simple Validation Example

Using the injected validators to check a

Person

instance:

<code>@Service
public class PersonService {

    @Resource
    private Validator validator;

    @Resource
    private org.springframework.validation.Validator springValidator;

    public void validate(Person person) {
        Set<ConstraintViolation<Person>> res = validator.validate(person);
        res.forEach(cv -> System.out.println(cv.getMessage()));
        System.out.println("----------------------");

        BindingResult errors = new MapBindingResult(new HashMap<>(), "person");
        springValidator.validate(person, errors);
        if (errors.hasErrors()) {
            errors.getAllErrors().forEach(oe -> System.out.println(oe.getDefaultMessage()));
        }
    }
}</code>

Test case demonstrates constraint violations:

<code>@SpringBootTest
class SpringBootValidationApplicationTests {

    @Resource
    private PersonService ps;

    @Test
    void testValidator() {
        Person person = new Person();
        person.setAge(-1);
        ps.validate(person);
    }
}</code>
<code>最小不能小于0
不能为null
----------------------
最小不能小于0
不能为null</code>

Custom Annotation Validation

Define a constraint annotation and its validator:

<code>@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PrefixConstraintValidator.class)
public @interface PrefixConstraint {
    String value() default "";
    String message() default "{validator.prefix.error}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}</code>

Validator implementation can inject other beans:

<code>public class PrefixConstraintValidator implements ConstraintValidator<PrefixConstraint, CharSequence> {

    @Resource
    private DataService ds;

    private String prefix;

    @Override
    public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
        ds.ak();
        if (value == null) {
            return false;
        }
        return ((String) value).startsWith(prefix);
    }

    @Override
    public void initialize(PrefixConstraint pc) {
        this.prefix = pc.value();
    }
}</code>

Method‑Level Validation

Enable method validation by registering

MethodValidationPostProcessor

and annotating beans with

@Validated

:

<code>@Bean
public MethodValidationPostProcessor validationPostProcessor() {
    return new MethodValidationPostProcessor();
}

@Service
@Validated
public class PersonService {

    @NotNull(message = "返回值不能为空")
    public Person findPerson(@NotEmpty(message = "ID 不能为空") String id) {
        return null;
    }
}</code>

When a constraint violation occurs, Spring throws

javax.validation.ConstraintViolationException

. A global exception handler can process it.

ConstraintViolationException example
ConstraintViolationException example

Other Configuration Options

The default

LocalValidatorFactoryBean

works for most cases; refer to its Javadoc for advanced settings such as message interpolation and traversal strategies.

https://docs.spring.io/spring-framework/docs/5.3.11/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
BackendJavaBean ValidationSpring BootCustom AnnotationValidator
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.