Maven モジュール A:
public interface RestValidator<A extends Annotation, T> extends ConstraintValidator<A, T>
public interface PhoneValidator extends RestValidator<PhoneNumber, String>
@Target(FIELD)
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneValidator.class) // This usually doesnt work since its a interface
public @interface PhoneNumber {
// JSR-303 required fields (payload, message, group)
}
public class Person {
@PhoneNumber
private String phoneNumber;
}
Maven モジュール B:
@Bean
LocalValidatorFactoryBean configurationPropertiesValidator(ApplicationContext context, AutowireCapableBeanFactory factory) {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setConstraintValidatorFactory(factory(context, factory));
return factoryBean;
}
private ConstraintValidatorFactory factory(final ApplicationContext context, final AutowireCapableBeanFactory factory) {
return new ConstraintValidatorFactory() {
@Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
if (RestValidator.class.isAssignableFrom(key)) {
return context.getBean(key);
} else {
return factory.createBean(key);
}
}
@Override
public void releaseInstance(ConstraintValidator<?, ?> instance) {
if (!(instance instanceof RestValidator<?, ?>)) {
factory.destroyBean(instance);
}
}
};
}
@Bean
WebMvcConfigurerAdapter webMvcConfigurerAdapter(final LocalValidatorFactoryBean validatorFactoryBean) {
return new WebMvcConfigurerAdapter() { // Adds the validator to MVC
@Override
public Validator getValidator() {
return validatorFactoryBean;
}
};
}
次に、Scope = Prototype を持つ PhoneValidator の @Component 実装があります。
私はこの解決策が嫌いで、Spring はデフォルトで Interface の実装を検索する必要があると思いますが、私よりもはるかに賢い人がそうしないことにしたと確信しています。