Spring Boot自定义校验无法注入Repository问题求助
问题根源
你的ContractorUniqueNameValidator虽标注了@Component,但默认情况下Hibernate Validator会自行实例化校验器,而非由Spring容器管理,导致@Autowired注入的contractorRepository始终为null,抛出空指针异常。
解决方案(推荐方案)
让Spring接管Validator的创建逻辑,使校验器纳入Spring容器管理,从而支持依赖注入:
- 添加Validator配置类
创建配置类注册LocalValidatorFactoryBean,让Spring负责生成Validator实例,确保所有自定义校验器由Spring初始化:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @Configuration public class ValidatorConfig { @Bean public LocalValidatorFactoryBean validator() { return new LocalValidatorFactoryBean(); } }
- 保留校验器的
@Component注解
确保ContractorUniqueNameValidator上的@Component注解保留,Spring会扫描并管理该类,Hibernate Validator会直接从Spring容器中获取校验器实例,而非自行创建。
备用方案(不推荐,仅作补充)
若不想配置全局Validator,可通过静态变量+Autowired setter的方式实现注入:
@Component public class ContractorUniqueNameValidator implements ConstraintValidator<ContractorUniqueName, Contractor> { private static ContractorRepository contractorRepository; @Autowired public void setContractorRepository(ContractorRepository repo) { contractorRepository = repo; } @Override public void initialize(ContractorUniqueName validator) { } @Override public boolean isValid(Contractor validateObject, ConstraintValidatorContext cxt) { return contractorRepository.countByIdNotAndNameEqualsIgnoreCase( validateObject.getId(), validateObject.getName() ) <= 0; } }
额外检查项
- 确认
ContractorUniqueNameValidator、ContractorRepository所在包处于Spring组件扫描范围内(主应用类的@SpringBootApplication默认扫描自身包及子包,若不在需添加@ComponentScan指定路径)。 - 控制器中
@Valid与BindingResult的顺序正确(BindingResult必须紧跟被校验参数后,否则Spring会直接抛出异常而非存入BindingResult)。
内容的提问来源于stack exchange,提问作者Curtis Snowden
相关产品推荐
相关产品推荐

