spring boot validator 源码分析
1: spring boot请求入口方法是org.springframework.web.servlet.DispatcherServlet#doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
.....
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
......
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new ServletException("Handler dispatch failed: " + err, err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new ServletException("Handler processing failed: " + err, err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
2:在doDispatch方法中
ha.handle(processedRequest, response, mappedHandler.getHandler())调用 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handleInternal 调用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal 调用
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
.....
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
....
return mav;
}
方法中调用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod 调用
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
.....
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
invocableMethod.setMethodValidator(this.methodValidator);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
....
invocableMethod.invokeAndHandle(webRequest, mavContainer);
...
return getModelAndView(mavContainer, modelFactory, webRequest);
}

这里请记住org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle调用
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
.....
}
org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest 调用
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
.....
return returnValue;
}
org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues调用
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
.......
try {
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled()) {
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw ex;
}
}
return args;
}
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument调用

从调试图片来看,是调用org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#resolveArgument方法
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
.....
if (binderFactory != null) {
String name = Conventions.getVariableNameForParameter(parameter);
ResolvableType type = ResolvableType.forMethodParameter(parameter);
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name, type);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
.......
}
return adaptArgumentIfNecessary(arg, parameter);
}

从上面截图来看,validators 指向是org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
2:分析LocalValidatorFactoryBean初始化和使用

LocalValidatorFactoryBean实现InitializingBean接口,我们只需要查看afterPropertiesSet方法。
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void afterPropertiesSet() {
Configuration<?> configuration;
.....
else {
GenericBootstrap bootstrap = Validation.byDefaultProvider();
if (this.validationProviderResolver != null) {
bootstrap = bootstrap.providerResolver(this.validationProviderResolver);
}
configuration = bootstrap.configure();
}
MessageInterpolator targetInterpolator = this.messageInterpolator;
if (targetInterpolator == null) {
targetInterpolator = configuration.getDefaultMessageInterpolator();
}
configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
.....
ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;
...
try {
this.validatorFactory = configuration.buildValidatorFactory();
setTargetValidator(this.validatorFactory.getValidator());
}
finally {
closeMappingStreams(mappingStreams);
}
}
核心代码是上面 GenericBootstrap LocaleContextMessageInterpolator validatorFactory 类,我们可以通过单元测试来验证
public abstract class BaseTest {
private Validator validator;
@BeforeEach
public void init(){
GenericBootstrap bootstrap = Validation.byDefaultProvider();
Configuration<?> configuration = bootstrap.configure();
MessageInterpolator targetInterpolator = configuration.getDefaultMessageInterpolator();
configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
ValidatorFactory validatorFactory = configuration.buildValidatorFactory();
this.validator = validatorFactory.getValidator();
}
protected <T>Set<ConstraintViolation<T>> validate(T object,Class<?>... groups){
return validator.validate(object,groups);
}
}
public class UserTest extends BaseTest {
@Test
public void testValidateUser(){
User user = new User();
Set<ConstraintViolation<User>> constraintViolations =validate(user);
constraintViolations.forEach(cv-> System.out.println(cv.getMessage()));
}
}