面试题:当接口定义的是下面这种方式的时候是用什么调用的?为什么?如何调用的?
@Controller
public class UserController {
@RequestMapping("/getUser")
public Object getUser(String name){
System.out.println("getuser");
return "success";
}
}
我们试想一下,一个类调用另一个类有几种方法,一是通过new一个类,再去调用,但是在DispatcherServlet里new一个类不现实,因为它根本不知道你定义的类名;二是通过继承一个类然后实现它,也就是上面所讲的,但它是有弊端的,一个类只能写一个接口,有多少个接口就有多少个类,那么剩下的就只能是反射了
直接到doDispatch方法中
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 {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//获取映射器,这里获取的是RequestMappingHandlerMapping
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//同样的,适配器也变成RequestMappingHandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet
{
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//调用自己写的处理器
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
//对返回的数据进行视图解析,跟(1)一样
this.processDispatchResult(processedRequest, response, mappedHandler, mv,(Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
这里主要看一下 ha.handle()方法:
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//调用一个本类的方法
return this.handleInternal(request, response, (HandlerMethod)handler);
}
handleInternal()
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
this.checkRequest(request);
ModelAndView mav;
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
// 是否通过 @SessionAttributes 注释声明了 session 属性。
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
//通过反射调用controller中的方法
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
//......
return mav;
}
invokeHandlerMethod
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
Object result;
try {
//.....
//重点是这一句,实际处理类,调用ServletInvocableHandlerMethod类的方法
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
if (!asyncManager.isConcurrentHandlingStarted()) {
ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
return var15;
}
result = null;
} finally {
webRequest.requestCompleted();
}
return (ModelAndView)result;
}
invokeAndHandle
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//调用目标方法之后获取的返回值,在这里也就是方法中的 success
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
this.setResponseStatus(webRequest);
if (returnValue == null) {
if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
} else if (StringUtils.hasText(this.getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
//....
}
invokeForRequest
org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//先获取方法中的参数
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Arguments: " + Arrays.toString(args));
}
//获取参数,调用方法
return this.doInvoke(args);
}
doInvoke
org.springframework.web.method.support.InvocableHandlerMethod#doInvoke
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(this.getBridgedMethod());
try {
//通过反射invoke调用目标方法
// getBridgedMethod()会获取到UserController类中的getUser()方法,this.getBean()就是UserController类,args为方法中的参数,即name
return this.getBridgedMethod().invoke(this.getBean(), args);
} catch (IllegalArgumentException var4) {
this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument";
throw new IllegalStateException(this.formatInvokeError(text, args), var4);
} catch (InvocationTargetException var5) {
Throwable targetException = var5.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException)targetException;
} else if (targetException instanceof Error) {
throw (Error)targetException;
} else if (targetException instanceof Exception) {
throw (Exception)targetException;
} else {
throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException);
}
}
}