1. 程式人生 > >SpringMVC原始碼分析--容器初始化(五)DispatcherServlet

SpringMVC原始碼分析--容器初始化(五)DispatcherServlet

上一篇部落格SpringMVC原始碼分析--容器初始化(四)FrameworkServlet我們已經瞭解到了SpringMVC容器的初始化,SpringMVC對容器初始化後會進行一系列的其他屬性的初始化操作,在SpringMVC初始化完成之後會呼叫onRefresh(wac)方法,它通過模板方式在子類DispatcherServlet中實現的。

onRefresh函式實現如下,其具體的實現就放到initStrategies函式中實現。

        /**
	 * This implementation calls {@link #initStrategies}.
	 */
	//初始化策略,完成SpringMVC預設實現類的初始化,onRefresh是在父類FrameworkServlet中呼叫
	@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}
initStrategies函式中初始化了一些springMVC執行過程中需要使用的預設的實現類,接下來我們分別介紹一下預設實現的 類。
       //初始化SpringMVC的一些策略,也是springMVC主要的元件
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);//檔案上傳解析,如果請求型別是multipart將通過MultipartResolver進行檔案上傳解析
		initLocaleResolver(context);//本地化解析
		initThemeResolver(context);//主題解析
		initHandlerMappings(context);//通過HandlerMapping,將請求對映到處理器
		initHandlerAdapters(context);//通過HandlerAdapter支援多種型別的處理器
		initHandlerExceptionResolvers(context);//如果執行過程中遇到異常,將交給HandlerExceptionResolver來解析
		initRequestToViewNameTranslator(context);//直接解析請求到檢視名
		initViewResolvers(context);//通過viewResolver解析邏輯檢視到具體檢視實現
		initFlashMapManager(context);//flash對映管理器
	}
initMultipartResolver初始化檔案上傳解析器,與檔案上傳的相關的操作,有關檔案上傳操作我們會仔細分析,這裡不做過多介紹。
        ////檔案上傳解析,如果請求型別是multipart將通過MultipartResolver進行檔案上傳解析
	private void initMultipartResolver(ApplicationContext context) {
		try {
			//bean id被寫死,在配置的時候需要注意,檔案上傳時需要注入bean名稱為multipartResolver的類
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Default is no multipart resolver.
			this.multipartResolver = null;
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
						"': no multipart request handling provided");
			}
		}
	}

initLocaleResolver是初始化一些多語言實現相關的類,在配置多語言本地化時會注入bean名稱為localeResolver,預設實現的類有FixedLocaleResolver ,SessionLocaleResolver ,CookieLocaleResolver, AcceptHeaderLocaleResolver 
        //本地化解析,支援web應用程式國際化,在springMVC應用程式中,使用者的區域是通過區域解析器事變的
	//spring採用的是預設區域解析器 AcceptHeaderLocaleResolver  ,通過檢驗HTTP請求的accept-language頭部來解析區域
	//這個頭部是有使用者的瀏覽器根據底層作業系統的區域設定進行設定,這個區域解析器無法改變使用者的區域,因為無法修改使用者
	//作業系統的區域設定
	private void initLocaleResolver(ApplicationContext context) {
		try {
			//在配置多語言本地化時會注入bean名稱為localeResolver,預設實現的類有FixedLocaleResolver ,SessionLocaleResolver ,CookieLocaleResolver, AcceptHeaderLocaleResolver 
			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +
						"': using default [" + this.localeResolver + "]");
			}
		}
	}
initThemeResolver與樣式相關的解析器,需要在配置檔案中注入bean名稱為themeResolver的,FixedThemeResolver, SessionThemeResolver和CookieThemeResolver
        //動態樣式支援
	private void initThemeResolver(ApplicationContext context) {
		try {
			//需要在配置檔案中注入bean名稱為themeResolver的,FixedThemeResolver, SessionThemeResolver和CookieThemeResolver
			this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ThemeResolver [" + this.themeResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug(
						"Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" +
								this.themeResolver + "]");
			}
		}
	}
initHandlerMappings初始化HandlerMapping,HandlerMapping的工作就是為每個請求找到合適的請求找到一個處理器handler
        //會載入HandlerMapping,預設使用BeanNameUrlHandlerMapping
	private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			//預設載入所有的HandlerMapping,
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				//陣列中含有多個HandlerMapping
				this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
			}
		}
	}
initHandlerAdapters是初始化HandlerAdapter,HandlerAdapter是真正呼叫Controller操作的類
        //初始化HandlerAdapters,預設使用的是SimpleControllerHandlerAdapter
	private void initHandlerAdapters(ApplicationContext context) {
		this.handlerAdapters = null;

		if (this.detectAllHandlerAdapters) {
			// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
			Map<String, HandlerAdapter> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
			if (!matchingBeans.isEmpty()) {
				//陣列中含有多個HandlerAdapters
				this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
				// We keep HandlerAdapters in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
			}
		}
		else {
			try {
				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
				this.handlerAdapters = Collections.singletonList(ha);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerAdapter later.
			}
		}

		
		//如果沒有設定HandlerAdapters,則獲取預設的配置
		if (this.handlerAdapters == null) {
			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
			}
		}
	}
initHandlerExceptionResolvers是初始化HandlerExceptionResolver,用來操作異常,接下來我們會對其進行詳細分析
        //初始化HandlerExceptionResolver
	private void initHandlerExceptionResolvers(ApplicationContext context) {
		this.handlerExceptionResolvers = null;

		if (this.detectAllHandlerExceptionResolvers) {
			// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
			Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
					.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
				// We keep HandlerExceptionResolvers in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
			}
		}
		else {
			try {
				HandlerExceptionResolver her =
						context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
				this.handlerExceptionResolvers = Collections.singletonList(her);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, no HandlerExceptionResolver is fine too.
			}
		}

		// Ensure we have at least some HandlerExceptionResolvers, by registering
		// default HandlerExceptionResolvers if no other resolvers are found.
		if (this.handlerExceptionResolvers == null) {
			this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
			}
		}
	}
initRequestToViewNameTranslator是初始化到ViewName的處理器。
        /* 返回一個對應的檢視名稱*/
	private void initRequestToViewNameTranslator(ApplicationContext context) {
		try {
			this.viewNameTranslator =
					context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate RequestToViewNameTranslator with name '" +
						REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator +
						"]");
			}
		}
	}
initViewResolvers初始化View的解析器
        //初始化viewResolver
	private void initViewResolvers(ApplicationContext context) {
		this.viewResolvers = null;

		if (this.detectAllViewResolvers) {
			// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
			Map<String, ViewResolver> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());
				// We keep ViewResolvers in sorted order.
				AnnotationAwareOrderComparator.sort(this.viewResolvers);
			}
		}
		else {
			try {
				ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
				this.viewResolvers = Collections.singletonList(vr);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default ViewResolver later.
			}
		}

		// Ensure we have at least one ViewResolver, by registering
		// a default ViewResolver if no other resolvers are found.
		if (this.viewResolvers == null) {
			this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
			}
		}
	}
initFlashMapManager初始化FlashMapManager,與連結跳轉相關的。
        //初始化 FlashMapManager
	private void initFlashMapManager(ApplicationContext context) {
		try {
			this.flashMapManager =
					context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using FlashMapManager [" + this.flashMapManager + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate FlashMapManager with name '" +
						FLASH_MAP_MANAGER_BEAN_NAME + "': using default [" + this.flashMapManager + "]");
			}
		}
	}

這樣就完成了SpringMVC工程啟動時初始化的所有工作了,主要就是完成IOC容器的初始化和一些預設實現的初始化,這樣就完成了SpringMVC的初始化工作,接下來就是對Controller的訪問連結的處理,我們會一步一步的寫原始碼部落格進行分析的。