//DispatcherServlet에서 요청을 받음
HttpServletRequest processedRequest = request;
// HandlerAdapter 에서 handle 실행
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// RequestMappingHandlerAdapter 가 받음
// handlerInternal 메소드에서 핸들러메소드를 invoke 함
mav = this.invokeHandlerMethod(request, response, handlerMethod);
// binderFactory 만듬
WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
// 따라가보면 만들고 있는데 여기 메소드도 들어가보면
DefaultDataBinderFactory factory = this.createDataBinderFactory(initBinderMethods);
// ServletRequestDataBinderFactory를 만들고 있다
protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods) throws Exception {
return new ServletRequestDataBinderFactory(binderMethods, this.getWebBindingInitializer());
}
// 이렇게 만들어진 binderFactory를 invocableMethod 안에 저장
invocableMethod.setDataBinderFactory(binderFactory);
// 그 다음 invokeAndHandle 실행
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
invokeAndHandle 에 들어가면 invokeForRequest를 실행한다
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
// 여기서 아큐먼트 값을 구하고 리턴 받는다
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
//getMethodArgumentValues 이 메소드 상세하게 보면
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
} else {
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
}
// 여기서 resolver를 받고 지금은 ServletModelAttributeMethodProcessor 라는 아큐먼트리졸버 구현체다
ModelAttributeMethodProcessor 의 resolveArgument 자세히 보자
resolveArgument
// 이름을 가져옴
String name = ModelFactory.getNameForParameter(parameter);
// 변수를 선언했는데 여기에 컨트롤러의 매개변수의 객체를 담아서 반환할 것이다
Object attribute;
// (1) 세션에 이미 저장된 것이 있으면 가져오는 로직
if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
if (attribute == null || ObjectUtils.unwrapOptional(attribute) == null) {
bindingResult = binderFactory.createBinder(webRequest, (Object)null, name).getBindingResult();
attribute = wrapAsOptionalIfNecessary(parameter, (Object)null);
}
}
// (2) 컨버터를 통해 만드는 과정
attribute = this.createAttribute(name, parameter, binderFactory, webRequest);
if (bindingResult == null)
// 여기서 factory가 binder 객체 생성
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name, type);
// attribute 가 null 이면 생성자에서 생성할 것인지 본다
if (attribute == null) {
this.constructAttribute(binder, webRequest);
attribute = wrapAsOptionalIfNecessary(parameter, binder.getTarget());
}
// 여기서 createObject해서 결과가 target에 담긴다
public void construct(ValueResolver valueResolver) {
Assert.state(this.target == null, "Target instance already available");
Assert.state(this.targetType != null, "Target type not set");
this.target = this.createObject(this.targetType, "", valueResolver);
if (!this.getBindingResult().hasErrors()) {
this.bindingResult = null;
if (this.typeConverter != null) {
this.typeConverter.registerCustomEditors(this.getPropertyAccessor());
}
}
}
// 리플렉션 기술을 통해서 값을 담는다
result = BeanUtils.instantiateClass(ctor, args);
setter 로 바인딩하는 것을 보자
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
((WebRequestDataBinder)binder).bind(request);
}
public void bind(WebRequest request) {
if (!this.shouldNotBindPropertyValues()) {
MutablePropertyValues mpvs = new MutablePropertyValues(request.getParameterMap());
if (request instanceof NativeWebRequest) {
NativeWebRequest nativeRequest = (NativeWebRequest)request;
MultipartRequest multipartRequest = (MultipartRequest)nativeRequest.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
this.bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
} else if (StringUtils.startsWithIgnoreCase(request.getHeader("Content-Type"), "multipart/form-data")) {
HttpServletRequest servletRequest = (HttpServletRequest)nativeRequest.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null && HttpMethod.POST.matches(servletRequest.getMethod())) {
StandardServletPartUtils.bindParts(servletRequest, mpvs, this.isBindEmptyMultipartFiles());
}
}
}
this.doBind(mpvs);
}
}