在自定义JSR-303验证器中使用@Autowired组件

时间:2013-10-25 14:37:31

标签: java spring dependency-injection spring-security bean-validation

我正在尝试为我的模型类实现一个自定义验证器,它自动装配我的自定义bean(通过@Component声明)。 在此,我跟随Spring documentation on that topic。我的AuthenticationFacade对象是根据this tutorial实现的。

但是,在运行测试时,Validator对象中的自动装配属性始终为null。那是为什么?

以下是我的代码的相关部分:

我的自定义bean AuthenticationFacadeImpl.java

@Component
public class AuthenticationFacadeImpl implements AuthenticationFacade {
    boolean hasAnyRole(Collection<String> roles) {
        // checks currently logged in user roles
    }
}

我的自定义约束HasAnyRoleConstraint.java

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

我的自定义验证器HasAnyRoleConstraintValidator.java

@Component
public class HasAnyRoleConstraintValidator implements ConstraintValidator<HasAnyRole, Object> {
    @Autowired
    AuthenticationFacade authenticationFacade;

    private String[] roles;

    @Override
    public void initialize(HasAnyRole hasAnyRole) {
        this.roles = hasAnyRole.value();
    }

    @Override
    public boolean isValid(Object target, ConstraintValidatorContext constraintValidatorContext) {
        return target == null || authenticationFacade.hasAnyRole(Arrays.asList(this.roles));
    }
}

模型类Article.java

@Entity
public class Article {
    // ...
    @HasAnyRole({"EDITOR", "ADMIN"})
    private String title;
    // ...
}

服务对象ArticleServiceImpl.java

@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private AuthenticationFacade authenticationFacade;

    @Autowired
    private Validator validator;

    @Override
    @PreAuthorize("hasAnyRole('ADMIN', 'EDITOR')")
    public boolean createArticle(Article article, Errors errors) {
        articleRepository.save(article);
        return true;
    }

Errors方法的createArticle对象是来自Spring控制器,它被赋予一个带有@Valid注释的模型对象。

存储库ArticleRepository.java使用Spring Data JPA的JpaRepository

public interface ArticleRepository extends JpaRepository<Article, Long> {
}

2 个答案:

答案 0 :(得分:0)

我现在通过抛弃Validator类的Dependency Injection来解决这个问题,而不是在构造函数中实例化AuthenticationFacadeImpl的实例。 仍然有趣,但如何将控制器中@Valid的使用与模型中的自定义验证器+ @Autowired属性相结合,而无需在代码中明确地调用验证器...

答案 1 :(得分:0)

如果您的验证器在Spring上下文之外被实例化,那么您可以使用Spring的AOP @Configurable魔法在上下文中注册它并获得自动装配工作。您需要的只是使用HasAnyRoleConstraintValidator注释@Configurable并启用编译时间或加载时间方面的编织。