總結
- 對requestMappingHandlerMapping進行initializeBean時register Handler
- http開始請求時,initHandlerMappings,DispatcherServlet 中handlerMappings賦值完成
- 最後在DispatcherServlet#doDispatch()中,用對應的HandlerAdapter和Handler通過反射去請求controller中方法
對requestMappingHandlerMapping進行initializeBean時register Handler
呼叫鏈:
AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#createBean() --> AbstractAutowireCapableBeanFactory#doCreateBean() --> AbstractAutowireCapableBeanFactory#initializeBean() --> AbstractAutowireCapableBeanFactory#invokeInitMethods() --> RequestMappingHandlerMapping#afterPropertiesSet() --> AbstractHandlerMethodMapping#afterPropertiesSet() --> AbstractHandlerMethodMapping#initHandlerMethods() --> AbstractHandlerMethodMapping#processCandidateBean --> AbstractHandlerMethodMapping#detectHandlerMethods() --> RequestMappingHandlerMapping#registerHandlerMethod() --> AbstractHandlerMethodMapping#registerHandlerMethod()
在AbstractHandlerMethodMapping#initHandlerMethods()中先獲取所有的beanName,再挑選出符合條件的進行處理
protected void initHandlerMethods() {
//獲取容器中所有beanName
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
判斷是Handler的才繼續呼叫detectHandlerMethods方法
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
......
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
滿足handler的條件是(RequestMappingHandlerMapping#isHandler()):@Controller或@RequestMapping進行註解
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
滿足條件的,進行註冊
RequestMappingHandlerMapping#registerHandlerMethod()
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
super.registerHandlerMethod(handler, method, mapping);
updateConsumesCondition(mapping, method);
}
AbstractHandlerMethodMapping#registerHandlerMethod()
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
完成註冊。AbstractHandlerMethodMapping#register()
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
validateMethodMapping(handlerMethod, mapping);
Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
for (String path : directPaths) {
this.pathLookup.add(path, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration config = initCorsConfiguration(handler, method, mapping);
if (config != null) {
config.validateAllowCredentials();
this.corsLookup.put(handlerMethod, config);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directPaths, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
initHandlerMappings
呼叫鏈:
Standardwrapper#initServlet() --> HttpServletBean#init() --> FrameworkServlet#initServletBean() --> FrameworkServlet#initWebApplicationContext() --> DispatcherServlet#onRefresh() --> DispatcherServlet#initStrategies() -->
DispatcherServlet#initHandlerMappings()
http請求時,先initHandlerMappings.
matchingBeans會儲存獲取到所有符合條件的,再給handlerMappings賦值
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
}
其中BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);會先呼叫AbstractApplicationContext#getBeansOfType(),再呼叫DefaultListableBeanFactory#getBeansOfType()
先獲取beanName requestMappingHandlerMapping,再根據beanName(requestMappingHandlerMapping)從容器獲取beanInstance。最後put到result中返回
@Override
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBeansOfType(
@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
//獲取requestMappingHandlerMapping
String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
Map<String, T> result = CollectionUtils.newLinkedHashMap(beanNames.length);
for (String beanName : beanNames) {
try {
////再根據beanName(requestMappingHandlerMapping)從容器獲取beanInstance
Object beanInstance = getBean(beanName);
if (!(beanInstance instanceof NullBean)) {
result.put(beanName, (T) beanInstance);
}
}
......
return result;
}
從而在initHandlerMappings給handlerMappings賦值完成
this.handlerMappings = new ArrayList<>(matchingBeans.values());
doDispatch
獲取當前請求的handler和HandlerAdapter
DispatcherServlet#doDispatch()
mappedHandler = getHandler(processedRequest);
DispatcherServlet#getHandler()
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
通過反射方式請求controller中方法:
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
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 {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
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;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
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 NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
}
}
}