zoukankan      html  css  js  c++  java
  • SpringMVC源码之Handler注册、获取以及请求controller中方法

    总结

    1. 对requestMappingHandlerMapping进行initializeBean时register Handler
    2. http开始请求时,initHandlerMappings,DispatcherServlet 中handlerMappings赋值完成
    3. 最后在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);
    			}
    		}
    	}
    }
    
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    一道面试题:按照其描述要求用java语言实现快速排序
    Tomcat容器运行struts2+spring+mybatis架构的java web应用程序简单分析
    关于oracle存储过程的一些知识点
    多动手试试,其实List类型的变量在页面上取到的值可以直接赋值给一个js的Array数组变量
    Chapter 5: Container
    统计文件夹下java代码行数的小程序--主要是学习任务队列的思想
    利用strut2标签自动生成form前端验证代码
    简单实现web单点登录
    Chapter 4: Tomcat Default Connector
    [python] 格式化方法 format
  • 原文地址:https://www.cnblogs.com/caozibiao/p/14002601.html
Copyright © 2011-2022 走看看