You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ConstraintValidator中@Autowired注入为空的问题解决求助

解决Hibernate Validator自定义校验器无法注入Spring Bean的问题

问题背景

需要实现跨多个DTO类的字段校验自定义注解,校验规则基于正则表达式,所有规则存储在配置服务器的JSON字符串中,通过@Value注解读取。使用ConstraintValidator实现自定义校验器后,发现校验器中@Autowired注入的ValidatorConfiguration始终为null。原因是ConstraintValidator由Hibernate而非Spring管理,无法直接访问Spring托管Bean。使用版本:org.hibernate.validator 6.2.5、Spring 5.3.25。

相关代码

自定义注解类

@Target({ ElementType.FIELD })
@Retention( RetentionPolicy.RUNTIME )
@Constraint(validatedBy = DynamicRegexValidator.class)
public @interface RegexValidatedField {

    String fieldName();
    String message() default "Invalid field";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

}

ConstraintValidator实现类

public class DynamicRegexValidator implements ConstraintValidator<RegexValidatedField, String> {

    @Autowired
    private ValidatorConfiguration validatorConfiguration;

    private String fieldName;

    @Override
    public void initialize(RegexValidatedField constraintAnnotation) {
        this.fieldName = constraintAnnotation.fieldName();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        ValidationRule rule = validatorConfiguration.getRuleForField(fieldName);
        if (rule == null || value == null) {
            return true;
        }

        if (!value.matches(rule.getRegex())) {
            return false;
        }

        return true;
    }
}

配置类

@Configuration
public class ValidatorConfiguration {

    @Value("${validation.rules:}")
    private String validationRulesJson;

    private Map<String, ValidationRule> validationRules;

    @PostConstruct
    public void init() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        validationRules = objectMapper.readValue(validationRulesJson, new TypeReference<Map<String, ValidationRule>>() {});
    }

    public ValidationRule getRuleForField(String fieldName) {
        return validationRules.get(fieldName);
    }

}

解决方案

方案一:通过Spring上下文静态获取Bean

创建Spring上下文工具类,用于静态获取Spring托管Bean:

@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        SpringContextHolder.applicationContext = context;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

修改DynamicRegexValidator,在初始化阶段从上下文获取ValidatorConfiguration:

public class DynamicRegexValidator implements ConstraintValidator<RegexValidatedField, String> {

    private ValidatorConfiguration validatorConfiguration;
    private String fieldName;

    @Override
    public void initialize(RegexValidatedField constraintAnnotation) {
        this.fieldName = constraintAnnotation.fieldName();
        // 从Spring上下文获取Bean
        this.validatorConfiguration = SpringContextHolder.getBean(ValidatorConfiguration.class);
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (validatorConfiguration == null) {
            return true; // 根据业务需求调整默认逻辑
        }
        ValidationRule rule = validatorConfiguration.getRuleForField(fieldName);
        if (rule == null || value == null) {
            return true;
        }

        return value.matches(rule.getRegex());
    }
}

方案二:自定义ConstraintValidatorFactory让Spring管理校验器

创建Spring托管的校验器工厂,让Hibernate使用该工厂创建校验器实例:

@Component
public class SpringConstraintValidatorFactory implements ConstraintValidatorFactory {

    private final AutowireCapableBeanFactory beanFactory;

    @Autowired
    public SpringConstraintValidatorFactory(AutowireCapableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
        // 由Spring创建校验器实例,支持Autowired注入
        return beanFactory.createBean(key);
    }

    @Override
    public void releaseInstance(ConstraintValidator<?, ?> instance) {
        beanFactory.destroyBean(instance);
    }
}

配置Hibernate Validator使用自定义工厂:

@Configuration
public class ValidatorConfig {

    @Autowired
    private SpringConstraintValidatorFactory validatorFactory;

    @Bean
    public Validator validator() {
        return Validation.byProvider(HibernateValidator.class)
                .configure()
                .constraintValidatorFactory(validatorFactory)
                .buildValidatorFactory()
                .getValidator();
    }
}

此方案无需修改原DynamicRegexValidator代码,@Autowired可正常注入Spring Bean。

注意事项

  • 方案一中需确保SpringContextHolder被Spring扫描到(处于@ComponentScan范围内)
  • 方案二中自定义的ValidatorBean会替换Spring默认的Validator实例,确保所有校验逻辑都使用该工厂创建的校验器

内容的提问来源于stack exchange,提问作者jun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:20:05