Backend Development 7 min read

Master Bean Validation in Spring 5: From Basics to Custom Constraints

Learn how to integrate Bean Validation with Spring 5.2.23, configure the validator, inject it, create custom constraints, and enable method‑level validation using MethodValidationPostProcessor, with complete code examples and execution results, including handling of constraint violations and bean registration steps.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Bean Validation in Spring 5: From Basics to Custom Constraints

Overview

Bean Validation offers a universal way to validate Java applications by declaring constraints on domain model properties. The runtime enforces these constraints. Built‑in constraints are available, and you can define custom ones. Example:

<code>public class User {
    @NotEmpty(message = "姓名不能为空")
    private String name;
    @Min(value = 1, message = "年龄必须大于1")
    private Integer age;
}</code>

The Bean Validation validator then checks instances of this class. For general API information see https://beanvalidation.org/ and for specific constraints refer to the Hibernate Validator documentation at https://hibernate.org/validator/ .

Configuring the Validation Provider

Spring fully supports the Bean Validation API and allows the validator provider to be configured as a Spring bean. You can expose javax.validation.ValidatorFactory or javax.validation.Validator for injection.

Use LocalValidatorFactoryBean to register the default validator:

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

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

This basic configuration automatically triggers bean validation initialization. Ensure a Bean Validation provider (e.g., Hibernate Validator) is on the classpath.

Injecting the Validator

LocalValidatorFactoryBean implements javax.validation.ValidatorFactory , javax.validation.Validator , and Spring’s org.springframework.validation.Validator . You can inject any of these interfaces into beans that need validation logic.

Direct injection of the Bean Validation API:

<code>import javax.validation.Validator;

@Service
public class MyService {
    @Autowired
    private Validator validator;
}</code>

Or inject Spring’s org.springframework.validation.Validator :

<code>import org.springframework.validation.Validator;

@Service
public class MyService {
    @Autowired
    private Validator validator;
}</code>

Custom Validation

Define a custom annotation:

<code>@Documented
@Constraint(validatedBy = ValidEmptyConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ValidEmpty {
    String message() default "";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}</code>

Implement the validation logic:

<code>@Component
@SuppressWarnings("rawtypes")
public class ValidEmptyConstraintValidator implements ConstraintValidator<ValidEmpty, Collection> {
    @Override
    public boolean isValid(Collection value, ConstraintValidatorContext context) {
        return !(value == null || value.isEmpty());
    }
}</code>

Use the custom constraint on a field:

<code>@ValidEmpty(message = "集合不能为空")
private List<String> list;</code>

Method Parameter and Return‑Value Validation

Enable method‑level validation by registering MethodValidationPostProcessor :

<code>@Configuration
public class AppConfig {
    @Bean
    public MethodValidationPostProcessor validationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
}</code>

Annotate target classes with @Validated and place constraint annotations on method parameters:

<code>public class User {
    @NotEmpty(message = "姓名不能为空")
    private String name;
    private Integer age;
}

@Validated
public class UserService {
    public void findById(@NotNull(message = "ID不能为空") Long id) {
        // ...
    }
}</code>

Register the beans and invoke the service:

<code>GenericApplicationContext context = new GenericApplicationContext();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
reader.registerBean(MethodValidationPostProcessor.class);
reader.registerBean(UserService.class);
context.refresh();
UserService us = context.getBean(UserService.class);
User user = new User();
us.save(user);
us.findById(null);
context.close();</code>

Resulting exception:

<code>Exception in thread "main" javax.validation.ConstraintViolationException: findById.arg0: ID不能为空
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:120)
    ...</code>

All steps demonstrate how to set up Bean Validation in Spring, inject validators, create custom constraints, and apply method‑level validation.

BackendJavaSpringBean ValidationCustom ConstraintsMethod Validation
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.