如何避免因为@Constraint valiatedBy而导致的层间交叉依赖?

mnemlml8  于 2022-09-20  发布在  Maven
关注(0)|答案(3)|浏览(163)

在我们的项目中,我们在单独的Maven模块中有服务层和DAO层。服务模块依赖于DAO模块,并与其实体协同工作。问题是,我们不能将使用来自服务层的一些服务的自定义JSR 303约束放在DAO实体中,因为这会创建从DAO层到服务层的反向引用,因为验证器类需要在Custom@Constraint的valiatedBy属性中引用。

有没有办法(使用标准的JSR303API)在运行时指定某个自定义约束的验证器类(或者以其他方式解决我们的问题)?内置约束具有空的valiatedBy属性,但我不知道是否有用于该属性的API。

uhry853o

uhry853o1#

我们在基于Spring的项目中也遇到了同样的问题。为了以最佳的Spring方式解决这个问题,我们将ConstraintValidator接口和实现分开。例如,在域层中,我们只有接口:

public interface UniqueValidator extends ConstraintValidator<Unique, String> {
}

在服务层中,我们实现该接口:

public class UniqueValidatorJpaImpl implements UniqueValidator {
    private EntityManager entityManager;
    ...
}

接下来,我们在Spring上下文中为UniqueValidatorJpaImpl声明一个Bean。

最后,为了让所有员工都能工作,我们扩展了SpringConstraintValidatorFactory。默认情况下,它只创建在valiatedBy中指定的类的新示例。我们通过首先在Spring上下文中查找相应类型的Bean来扩展它:

public class SpringConstraintValidatorFactoryEx implements ConstraintValidatorFactory {

    private final Logger logger = LoggerFactory.getLogger(SpringConstraintValidatorFactoryEx.class);

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
        T bean = null;

        try {
            logger.info("Trying to find a validator bean of class " + key.getSimpleName());
            bean = this.beanFactory.getBean(key);
        } catch (BeansException exc) {
            logger.info("Failed to find a bean of class " + key.getSimpleName());
        }

        if (bean == null) {
            try {
                logger.info("Creating a new validator bean of class " + key.getSimpleName());
                bean = this.beanFactory.createBean(key);
            } catch (BeansException exc) {
                logger.info("Failed to create a validator of class " + key.getSimpleName());
            }
        }

        if (bean == null) {
            logger.warn("Failed to get validator of class " + key.getSimpleName());
        }

        return bean;
    }

}
t3irkdon

t3irkdon2#

您可以使用基于XML的约束Map将验证器分配给您的约束,以避免从注解到验证器实现的引用。

BV 1.1 EG也是discussing在这方面的一些改进。请随时在mailing list上就该问题发表意见。

j9per5c4

j9per5c43#

对于Spring5,您需要实现定制的ConstraintValidatorFactory:

@Component
class CustomConstraintValidatorFactory(
  private val beanFactory: AutowireCapableBeanFactory
) : SpringConstraintValidatorFactory(beanFactory) {

  override fun <T : ConstraintValidator<*, *>> getInstance(key: Class<T>): T = this.beanFactory.getBean(key)

}

并为LocalValidatorFactoryBean创建配置:

@Configuration
class ValidationConfiguration(
  private val customConstraintValidatorFactory: CustomConstraintValidatorFactory
) {

  @Bean
  fun getValidator(): LocalValidatorFactoryBean {
    val bean = LocalValidatorFactoryBean()
    bean.constraintValidatorFactory = customConstraintValidatorFactory
    return bean
  }
}

以柯特林表示的代码

相关问题