在我们的项目中,我们在单独的 Maven 模块中有服务和 DAO 层。服务模块依赖于 DAO 模块并与其实体一起工作。问题是我们不能在 DAO 实体中放置使用来自服务层的一些服务的自定义 jsr 303 约束,因为这会创建从 DAO 层到服务层的反向引用,因为 validator 类需要在自定义的 validatedBy 属性中引用@约束。
有没有办法(使用标准 jsr 303 api)在运行时指定某些自定义约束的 validator 类(或以任何其他方式解决我们的问题)?内置约束具有空的 validatedBy 属性,但我不知道是否有相应的 api。
最佳答案
我们在基于 Spring 的项目中遇到了同样的问题。为了以最好的 Spring 方式解决它,我们拆分了 ConstraintValidator 接口(interface)和实现。例如在领域层我们只有接口(interface):
public interface UniqueValidator extends ConstraintValidator<Unique, String> {
}
在服务层我们实现了这个接口(interface):
public class UniqueValidatorJpaImpl implements UniqueValidator {
private EntityManager entityManager;
...
}
接下来我们在 Spring Context 中为 UniqueValidatorJpaImpl 声明一个 bean。
最后,为了让所有员工工作,我们扩展了 SpringConstraintValidatorFactory。默认情况下,它只创建在 validatedBy 中指定的类的新实例。我们通过首先在 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;
}
}
关于java - 由于@Constraint validatedBy,如何避免层之间的交叉依赖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11720726/