SpringMVC源码笔记(一) DispatcherServlet.init

58 篇文章 0 订阅
12 篇文章 0 订阅

目录

onRefresh

HandlerMapping

SimpleUrlHandlerMapping

BeanNameUrlHandlerMapping

RequestMappingHandlerMapping

detectHandlerMethods

getMappingForMethod

registerHandlerMethod

HandlerAdapter 

SimpleControllerHandlerAdapter

RequestMappingHandlerAdapter

afterPropertiesSet

handle


SpringMVC的核心就是DispatcherServlet,本质还是一个Servlet,用于分发HTTP请求,调用相应的Handler处理请求。Servlet的生命周期是初始化init(),处理请求service(),销毁destroy(),挨个学习之

	public final void init() throws ServletException {
		initServletBean();
	}

	protected final void initServletBean() throws ServletException {
		try {
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();// 空方法
		}
		catch (ServletException | RuntimeException ex) {
			this.logger.error("Context initialization failed", ex);
			throw ex;
		}
	}

	protected WebApplicationContext initWebApplicationContext() {
        // 从ServletContext获取Spring父容器,如果有,那么springmvc子容器需要和父容器进行关联
        // 没有也不影响
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;

        // 为什么init时context会不为空?
        // 因为FrameworkServlet实现了ApplicationContextAware 接口,在作为bean交给spring容器管理时会调用setApplicationContext将容器注入进来
		if (this.webApplicationContext != null) {
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
               
				if (!cwac.isActive()) {
                     // 如果容器还没有调用refresh方法,关联父容器,然后调用refresh
                     // 但是我还不知道哪种方式能走到这,被ApplicationContextAware 注入了webApplicationContext,一般容器已经refresh过了
					if (cwac.getParent() == null) {
						cwac.setParent(rootContext);
					}
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		if (wac == null) {
            // 若当前ServletContext已存在刷新好的webapplicationcontext,提供了路子去查询,web.xml配置
            // <init-param>     
          //    <param-name>contextAttribute</param-name>
          //    <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
          // </init-param> 
            // 像上边配置这样,就是spring和springmvc容器使用同一个容器了
			wac = findWebApplicationContext();
		}
		if (wac == null) {
            // 既没注入又没配置,则创建,实例默认是XmlWebApplicationContext
            // 并调用context.refresh,加载xml文件中的配置
			wac = createWebApplicationContext(rootContext);
		}

		if (!this.refreshEventReceived) {
            // 加载springmvc的九组件,组件此时已经被实例化为bean,这一步其实是在选择相应的组件实例
			onRefresh(wac);
		}

		if (this.publishContext) {
            // 将当前context设置到ServletContext中
            // attrName = org.springframework.web.servlet.FrameworkServlet.CONTEXT. + servlet名
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
		}

		return wac;
	}

onRefresh

各组件的bean已经被加载到当前springmvc容器中,这一步是选择相应的组件实例关联到dispatcherServlet中 。组件除了文件解析之外都有默认组件,默认组件配置在DispatcherServlet同目录的DispatcherServlet.properties中,如下

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	protected void initStrategies(ApplicationContext context) {
        // context.getBean("multipartResolver", MultipartResolver.class)
        // 关联配置的文件解析,没有默认空
		initMultipartResolver(context);

        // context.getBean("localeResolver", LocaleResolver.class)
        // 国际化处理,没配默认org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
		initLocaleResolver(context);

        // context.getBean("themeResolver", ThemeResolver.class)
        // 主题处理,没有默认org.springframework.web.servlet.theme.FixedThemeResolver
		initThemeResolver(context);

        // 查询context下处理器映射器HandlerMapping.class实现类,一般都会使用下边两个
        // BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
		initHandlerMappings(context);

        // 查询context下处理器适配器HandlerAdapter.class实现类,常见的
        // RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter
		initHandlerAdapters(context);

        // 异常处理器
		initHandlerExceptionResolvers(context);

        // 视图名称翻译器
		initRequestToViewNameTranslator(context);

        // 页面渲染处理器
		initViewResolvers(context);

        // 参数传递管理器
		initFlashMapManager(context);
	}

 下边阅读最常见的HandlerMapping和HandlerAdapter组件,其他的再说吧

HandlerMapping

HandlerMapping组件充当url和Controller之间映射关系配置的角色,接口如下,根据请求获取对应的处理器Handler,HandlerExecutionChain是Handler的马甲,封装了一层

public interface HandlerMapping {
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

来看常用的几个实现类的源码 

SimpleUrlHandlerMapping

配置方法如图

配置一个class为SimpleUrlHandlerMapping的Bean,mappings属性中配置处理器路径和处理器类的对应关系,每个处理器类也需要作为bean配置。

类核心代码如下,在创建bean实例的时候,Spring调用setMappings将xml中的mappings配置设置到urlMap,这时只是url和beanName的对应关系,AbstractUrlHandlerMapping父类实现了ApplicationContextAware接口,所以会进入initApplicationContext方法中初始化,在registerHandlers()方法中取出urlMap中的beanName,根据beanName获取对应Bean对象,然后组成真正的url和Controller的对应关系存放在父类属性handlerMap中

public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {

	private final Map<String, Object> urlMap = new LinkedHashMap<>();

	public SimpleUrlHandlerMapping() {
	}
	
	public void setMappings(Properties mappings) {
		CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
	}

	@Override
	public void initApplicationContext() throws BeansException {
		super.initApplicationContext();
		registerHandlers(this.urlMap);
	}

	protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
		if (urlMap.isEmpty()) {
			logger.trace("No patterns in " + formatMappingName());
		}
		else {
			urlMap.forEach((url, handler) -> {
				// Prepend with slash if not already present.
				if (!url.startsWith("/")) {
					url = "/" + url;
				}
				// Remove whitespace from handler bean name.
				if (handler instanceof String) {
					handler = ((String) handler).trim();
				}
				registerHandler(url, handler);
			});
			
		}
	}

}

getHandler(HttpServletRequest request)

处理请求的时候使用getHandler()来获取请求对应的处理器,核心就是从handlerMap中根据url获取对应的handler,套层马甲HandlerExecutionChain返回

	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        //。。。
		return executionChain;
	}

	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		request.setAttribute(LOOKUP_PATH, lookupPath);
		Object handler = lookupHandler(lookupPath, request);
		return handler;
	}

	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
        // 看了半天,核心就是这里,从handlerMap中根据url获取
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			// Bean name or resolved handler?
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			return buildPathExposingHandler(handler, urlPath, urlPath, null);
		}

        return handler;
    }

BeanNameUrlHandlerMapping

配置如下

与SimpleUrlHandlerMapping同源,都是继承自AbstractUrlHandlerMapping,都是将url和handler对应关系放到handlerMap,不同的是BeanNameUrlHandlerMapping将xml配置文件中所有beanName是斜杠开头的bean都视为handler注册到BeanNameUrlHandlerMapping的handlerMap

public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {

	private boolean detectHandlersInAncestorContexts = false;

	public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) {
		this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts;
	}

	@Override
	public void initApplicationContext() throws ApplicationContextException {
		super.initApplicationContext();
		detectHandlers();
	}

	protected void detectHandlers() throws BeansException {
        // 获取当前容器所有的beanName
		ApplicationContext applicationContext = obtainApplicationContext();
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		for (String beanName : beanNames) {
            // 获取符合条件的bean,注册为handler
			String[] urls = determineUrlsForHandler(beanName);
			if (!ObjectUtils.isEmpty(urls)) {
				// 从容器中根据beanName获取bean并放入handlerMap中
				registerHandler(urls, beanName);
			}
		}
	}

	protected abstract String[] determineUrlsForHandler(String beanName);

}

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {

    // ‘/’开头的beanName,注册为handler
	protected String[] determineUrlsForHandler(String beanName) {
		List<String> urls = new ArrayList<>();
		if (beanName.startsWith("/")) {
			urls.add(beanName);
		}
		String[] aliases = obtainApplicationContext().getAliases(beanName);
		for (String alias : aliases) {
			if (alias.startsWith("/")) {
				urls.add(alias);
			}
		}
		return StringUtils.toStringArray(urls);
	}
}

RequestMappingHandlerMapping

注解方式的handlerMapping(@Controller)

在Bean初始化后的afterPropertiesSet()方法中进行Controller的处理,获取controller中被@RequestMapping注解的方法,并封装相关信息到RequestMappingHandlerMapping中

    private static final String SCOPED_TARGET_NAME_PREFIX = "scopedTarget.";

	@Override
	public void afterPropertiesSet() {
		initHandlerMethods();
	}

	protected void initHandlerMethods() {
		for (String beanName : getCandidateBeanNames()) {
            // springaop的狸猫换太子,将原bean对象的beanName前缀改为scopedTarget.beanName
            // 而beanName对应的bean对象替换为了代理对象,这里只处理代理对象
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);
			}
		}
	}

	protected void processCandidateBean(String beanName) {
        // 获取bean类的class
		Class<?> beanType = null;
		try {
			beanType = obtainApplicationContext().getType(beanName);
		}
		catch (Throwable ex) {
			// An unresolvable bean type, probably from a lazy bean - let's ignore it.
			if (logger.isTraceEnabled()) {
				logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
			}
		}

         // 判断如果类有controller注解或RequestMapping,表示是个handlerMapping
         // 再进一步获取其中定义的处理方法
		if (beanType != null && isHandler(beanType)) {
			detectHandlerMethods(beanName);
		}
	}

	protected boolean isHandler(Class<?> beanType) {
		return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
				AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
	}

detectHandlerMethods

	protected void detectHandlerMethods(Object handler) {
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
            // 如果是CGLIB代理的类,获取源类
			Class<?> userType = ClassUtils.getUserClass(handlerType);

            // MethodIntrospector.selectMethods工具类方法,是用来获取类中某些符合条件的method列表
            // MetadataLookup函数式接口是选择符合条件方法的具体逻辑
            // 这里用来获取被requestMapping注解的方法
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});

            // 将查找出来的方法列表挨个注册到RequestMappingHandlerMapping中
			methods.forEach((method, mapping) -> {
                // 这里没搞懂,看着是用来获取AOP代理包装后的Method,但是我测了测invocableMethod==method,暂时没弄明白,略过
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                // 注册handler方法和mapping的对应关系
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
	}

getMappingForMethod

	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {        
        // 获取方法上注解的@RequestMapping注解,并封装为RequestMapypingInfo对象
		RequestMapypingInfo info = createRequestMappingInfo(method);
		if (info != null) {
            // 获取Controller类上注解的@RequestMapping注解,并封装为RequestMapypingInfo对象
			RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
			// 合并相关信息,请求路径合并
            if (typeInfo != null) {
				info = typeInfo.combine(info);
			}
			String prefix = getPathPrefix(handlerType);
			if (prefix != null) {
				info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
			}
		}
		return info;
	}

	private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
		RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
		RequestCondition<?> condition = (element instanceof Class ?
				getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
		return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
	}

	protected RequestMappingInfo createRequestMappingInfo(
			RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {

		RequestMappingInfo.Builder builder = RequestMappingInfo
				.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
				.methods(requestMapping.method())
				.params(requestMapping.params())
				.headers(requestMapping.headers())
				.consumes(requestMapping.consumes())
				.produces(requestMapping.produces())
				.mappingName(requestMapping.name());
		if (customCondition != null) {
			builder.customCondition(customCondition);
		}
		return builder.options(this.config).build();
	}

registerHandlerMethod

	protected void registerHandlerMethod(Object handler, Method method, T mapping) {
		this.mappingRegistry.register(mapping, handler, method);
	}

    public void register(T mapping, Object handler, Method method) {
            // 加锁
			this.readWriteLock.writeLock().lock();
			try {
                // controller类和对应method 封一个马甲
				HandlerMethod handlerMethod = createHandlerMethod(handler, method);
                // 校验请求路径是否有重复
				validateMethodMapping(handlerMethod, mapping);

                // 以下就是保存mapping和方法的对应关系、请求路径和mapping对应等等
				this.mappingLookup.put(mapping, handlerMethod);

				List<String> directUrls = getDirectUrls(mapping);
				for (String url : directUrls) {
					this.urlLookup.add(url, mapping);
				}

				String name = null;
				if (getNamingStrategy() != null) {
					name = getNamingStrategy().getName(handlerMethod, mapping);
					addMappingName(name, handlerMethod);
				}

				CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
				if (corsConfig != null) {
					this.corsLookup.put(handlerMethod, corsConfig);
				}

				this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
			}
			finally {
				this.readWriteLock.writeLock().unlock();
			}
		}

getHandler(HttpServletRequest request)

	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		request.setAttribute(LOOKUP_PATH, lookupPath);
		this.mappingRegistry.acquireReadLock();
		try {
            // 从上边各种对应关系中获取匹配的HandlerMethod返回,详细的代码暂时没看
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

HandlerAdapter 

public interface HandlerAdapter {
	boolean supports(Object handler);

	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    long getLastModified(HttpServletRequest request, Object handler);
}

SpringMVC的HandlerMapping定义了多种配置处理器的方式,每种方式的处理器不同的实现方式,例如实现Controller接口、@Controller/@RequestMapping注解配置等等,实现不同所以调用方式也不同,那么在springmvc通过handlerMapping查找到具体的Handler实例时,就需要写很多if...else...来根据不同的实现方式进行调用。

而HandlerAdapter就用来解决这个if..else。采用适配器模式(通过组合、继承的方式将某个不符合预期的接口转换为所需要的接口)。

  1. supports(handler)   返回本适配器是否支持该类型的处理器
  2. handle(request, response, handler)  进行适配调用

下边是我的测试代码,随便一个类作为实现的handler,增加一个HandlerAdapter使这个类能由springmvc管理并进行调用

handler

public class Test2Controller {
    public ModelAndView aaaa(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("dadasda");
        return null;
    }
}

xml配置

    <bean name="/tests" class="com.lyq.enjoy.test.Test2Controller"></bean>

adapter

@Component
public class MyHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
       // 表示本适配器只支持Test2Controller类型的处理器
        Class clazz = handler.getClass();
        if (handler instanceof String) {
            clazz = SpringBeanUtil.getBean((String) handler).getClass();
        }
        return clazz.equals(Test2Controller.class);
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         // 适配调用
        return ((Test2Controller) handler).aaaa(request, response);
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return 0;
    }
}

SimpleControllerHandlerAdapter

比较简单,这就是继承Controller方式所使用的适配器

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}

	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return ((Controller) handler).handleRequest(request, response);
	}

	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}

}

RequestMappingHandlerAdapter

@RequestMapping类型的Handler的适配器

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
		implements BeanFactoryAware, InitializingBean {

	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}
}

主要的作用是

  1. 调用handler前,@RequestParam/@ModelAttribute相关的参数转换,将参数转换为controller中方法所需要的参数
  2. 调用handler执行处理
  3. 对handler返回值处理,统一封装为ModelAndView

来详细看源码处理,RequestMappingHandlerAdapter实现了InitializingBean,那么先来看afterPropertiesSet()初始化方法

afterPropertiesSet

 各种组件的初始化:@ControllerAdvice配置的获取、参数解析器、返回值解析器的获取等

	public void afterPropertiesSet() {
		// 先处理@ControllerAdvice注解,这都是些全局配置
        // 全局异常处理、请求入参处理、响应参数处理
		initControllerAdviceCache();

        // handlerMethod的请求参数转换器,可以自定义(WebMvcConfigurer.addArgumentResolvers)
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}

        // 参数绑定
		if (this.initBinderArgumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}

        // 返回值处理器,将返回值处理为ModleAndView
		if (this.returnValueHandlers == null) {
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

	private void initControllerAdviceCache() {
		if (getApplicationContext() == null) {
			return;
		}

        // 获取容器中所有@ControllerAdvice注解的bean
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

		List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();

		for (ControllerAdviceBean adviceBean : adviceBeans) {
			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {
				throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
			}

            // 获取类中定义的全局的@ModelAttribute注解方法,优先于Controller中定义的@ModelAttribute
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
			}
            
            // 获取类中定义的全局的@InitBinder注解方法,优先于Controller中定义的@InitBinder
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
				this.initBinderAdviceCache.put(adviceBean, binderMethods);
			}

            // RequestBodyAdvice/ResponseBodyAdvice用于在请求前后进行统一参数处理
            // 如果该ControllerAdvice还实现了RequestBodyAdvice/ResponseBodyAdvice
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}

	}

handle

 判断是否需要对session加锁,然后调用handlerMethod

	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// 判断当前session是否只允许单线程处理请求,如果是,加锁处理
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

        // Cache-Control请求头相关处理,暂时不懂,先看主干逻辑
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}

1、获取全局和Controller中的InitBinder 和 ModelAttribute

2、执行ModelAttribute方法

3、参数转换、调用handlerMethod、返回值转换

	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
            // 获取ControllerAdvice定义的全局InitBinder和Controller中定义的InitBinder
            // 准备进行参数绑定
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

            // 获取ControllerAdvice定义的全局ModelAttribute和Controller中定义的ModelAttribute
            // 在调用HandlerMethod方法之前调用
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

            // handlerMethod的一层封装
			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);

            // 调用上边查找到的ModelAttribute方法
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

            // 异步请求处理的代码,暂时忽略
			。。。。。

            // 对请求参数进行处理
            // 调用HandlerMethod
            // 将返回值封装为一个ModelAndView对象
			invocableMethod.invokeAndHandle(webRequest, mavContainer);

            // 如果请求已经返回客户端,返回null,否则构造ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

        // 参数转换和调用handlermethod
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		// 如果方法被@ResponseStatus注解,重置响应状态码和响应信息
        setResponseStatus(webRequest);
    
        // 如果方法被@ResponseStatus注解,返回值为null,直接返回处理完毕
        // 如果注解配置了Reason属性,不管有没有返回值都不予理睬
        // returnValue == null的其他两个或分支不知道
		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

         // 处理返回值,封装为ModelAndView
		mavContainer.setRequestHandled(false);

		this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}

	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		return doInvoke(args);
	}

getMethodArgumentValues

获取方法参数类型,循环挑选对应的解析器进行转换,默认的转换器列表见下图,详细的后续有空写写

	protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {
			return EMPTY_ARGS;
		}

		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
			if (!this.resolvers.supportsParameter(parameter)) {
				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
			}
			
			args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);

		}
		return args;
	}

this.returnValueHandlers.handleReturnValue

对返回值的处理也是类似,有很多的处理器,从中挑选相应的处理器进行处理

 过两天有空再准备将上边的某些部分,比如@InitBinder、@ModelAttribute、异步请求、HandlerMethodArgumentResolverHandlerMethodReturnValueHandler还有异常处理HandlerExceptionResolver拉出来详细看看

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值