【发布时间】:2012-09-22 11:32:13
【问题描述】:
我在自定义约束验证器中遇到 bean 自动装配问题。没有使用 Spring 的 LocalValidatorFactoryBean 给出约束验证器实例。 JSR-303 提供程序是 hibernate-validator 4.2.0.Final。
Spring 配置摘录:
<!-- JSR 303 validation -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
自定义约束验证器:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.model.Subject;
import com.services.SomeTypeService;
public class ReadOnlyValidator implements ConstraintValidator<ReadOnly, String> {
@Autowired
private SomeTypeService someTypeService;
@Override
public void initialize(ReadOnly constraintAnnotation) { }
@Override
public boolean isValid(String type, ConstraintValidatorContext context) {
try {
if (null != type) {
return !someTypeService.isReadonly(type);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
注释:
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )
@Retention(RUNTIME)
@Constraint(validatedBy = ReadOnlyValidator.class)
@Documented
public @interface ReadOnly {
String message() default "{constraints.subjecttype.readonly}";
public abstract Class<?>[] groups() default {};
public abstract Class<? extends Payload>[] payload() default {};
}
一些服务:
@Validated
public interface SomeService {
...
public void updateType(@ReadOnly String type) throws SomeException;
...
}
SomeServiceImpl :
@Service
public class SomeServiceImpl implements SomeService {
...
public void updateType(String type) throws SomeException {
// do something
}
...
}
SomeTypeService 是另一个不依赖于 SomeService 的 @Service 注释 bean ...
问题是我得到一个 NPE,因为自动装配不起作用;其他人正在管理自定义验证器实例,而不是 Spring ...
提前感谢任何类型的建议。
【问题讨论】:
-
Question Claudiu - 你有两个不同的应用程序上下文 - 一个通过 ContextLoaderListener 声明,一个通过 DispatcherServlet,因为你在服务方法级别有@validated,你可能需要在根中声明一个 LocalValidatorFactoryBean网络应用程序上下文也是?
-
嗯,我确实发现了一些与 LocalValidatorFactoryBean 实例数量相关的异常情况。我在“问题”描述中给出的声明位于 service-content.xml => 这是一个实例。使用
=> 时会自动创建另一个实例 => 我们对拥有根 Web 应用程序是正确的。 -
在验证只创建了一个 LocalValidatorFactoryBean 实例后,我开始验证创建了多少个 ReadOnlyValidator 实例。使用 jmap -histo:live
| grep "ReadOnlyValidator",我注意到只创建了一个实例,但仅在第一次调用 updateType 服务方法时才创建,而不是在初始化 LocalValidatorFactBean 时。我认为休眠验证引擎只是创建自己的约束验证器实例。我将如何“强制” LocalValidatorFactoryBean 管理 ReadOnlyValidator 实例以便可以使用 bean 接线?
标签: spring validation customvalidator hibernate-validator