【问题标题】:Spring Boot: Why is an autowired object in Custom Validator class is null?Spring Boot:为什么自定义验证器类中的自动装配对象为空?
【发布时间】:2021-02-17 14:38:08
【问题描述】:

以下代码在 isValid() 函数内的 teamResource 自动连接对象上产生 null:

@Component //I am not sure it is required he
public class TeamIdValidator implements ConstraintValidator<TeamIdConstraint, Integer> {
    
    @Autowired private TeamResource teamResource;
    
    public TeamIdValidator() {
    }

    @Override
    public void initialize(TeamIdConstraint teamIdConstraint) {
        // this.teamIdConstraint = teamIdConstraint;
    }

    @Override
    public boolean isValid(Integer teamId, ConstraintValidatorContext cxt) {

        int numOfAvailableTeams = teamResource.retrieveAllTeams().size(); //teamResource is null :(

        return teamId < 0 || teamId >= numOfAvailableTeams;
    }
}

团队资源类:

@RestController
@CrossOrigin
public class TeamResource {
    
    @Autowired private TeamRepository teamRepository;
    
    public TeamResource() {
    }
    ...

   //mapping methods
}

如果相关的话……

@Documented
@Constraint(validatedBy = TeamIdValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface TeamIdConstraint {
    
    String message() default "Invalid team id!";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

为什么teamResource 为空?

它没有在其他任何地方用 new 显式初始化。

【问题讨论】:

  • 臭名昭著的“自动装配到 ConstraintValidator”的东西怎么样?也许thisthis 有帮助?我记得在同样的问题上苦苦挣扎,原因可能是 ConstraintValidators 没有像“正常” Bean 那样“注入”但是(不再记得了)。不管你是否使用@Component
  • 我会检查你的链接。谢谢:)
  • 我怀疑实例是由 Spring 以外的东西创建的 - 验证器框架。为什么不在 TeamIdValidator 空构造函数中设置断点并检查堆栈跟踪 - 大概它被 Spring 初始化一次,然后又被其他东西初始化。调用 isValid 时检查对象 ID - 我敢打赌它是非 Spring bean 实例。
  • @pirho 你的链接是完全相关的——几周前我一直在努力解决这个问题。默认方式是休眠方式。
  • @ggr 你能详细说明一下方法吗?有具体的链接吗?

标签: spring spring-boot hibernate spring-data-jpa


【解决方案1】:

已经在 cmets 中提到过,但是声明一个这样的 bean

@Configuration
public class ValidationConfig{

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor(Validator validator) {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator);
        return methodValidationPostProcessor;
    }

}

删除所有@autowired,更喜欢构造函数注入。 (上网查查原因)。

然后,将 RestContoller 注入验证器是没有意义的。

【讨论】:

  • 谢谢ggr,但正如我上面问的,我应该把这个方法放在哪里?在 TeamIdValidator 类中?
  • 查看编辑。也许你应该尝试了解 Spring 是如何工作的,这只是框架的一些基础知识。
  • 嗯,是的……对我来说,bean 应该放在 Configuration 注释类中可能仍然不是自动的。我会记住的 :) 无论如何,我添加了这个类并且流程按预期通过。我从 teamResource 字段中删除了 Autowired 注释,并添加了 public TeamIdValidator(TeamResource teamResource) { this.teamResource = teamResource;结果是:“HV000064: 无法实例化 ConstraintValidator: com.ttt.bbsim.validation.TeamIdValidator.
  • 也许你也应该配置 methodValidationPostProcessor bean(见编辑)
猜你喜欢
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 2019-09-14
  • 2017-09-07
  • 2017-03-14
相关资源
最近更新 更多