本文所用源代码基于 Spring Web MVC 5.1.4.RELEASE

概述

DispatcherServlet#initLocaleResolver方法用于准备DispatcherServlet处理请求时所使用的LocaleResolver策略组件对象。

#initLocaleResolver首先尝试从容器(及其祖先容器)获取名称为localeResolverbean组件对象,记录到DispatcherServlet实例成员属性localeResolver。如果容器中名称为localeResolverbean组件不存在,则创建缺省的LocaleResolver对象记录到localeResolver

根据上面大致的介绍,我们可以看出:

  1. DispatcherServlet优先使用注册到容器中名为localeResolverLocaleResolver策略组件。利用这一特性,开发人员可以注册一个自定义的LocaleResolver,但必须使用名称localeResolver
  2. DispatcherServlet的属性localeResolver总是会对应一个LocaleResolver策略组件,如果容器中名称为localeResolver的组件不存在,则DispatcherServlet会缺省创建一个LocaleResolver供使用。

基于@EnableWebMvc+Java ConfigSpring MVC应用缺省情况下,容器中并没有注册的LocaleResolver组件,所以这里会创建一个缺省的LocaleResolver组件,使用的实现类是AcceptHeaderLocaleResolver,如下DispatcherServlet.properties所定义所示。

源代码解析

方法 #initLocaleResolver

	/**
	 * Initialize the LocaleResolver used by this class.
	 * If no bean is defined with the given name in the BeanFactory for this namespace,
	 * we default to AcceptHeaderLocaleResolver.
	 */
	private void initLocaleResolver(ApplicationContext context) {
		try {
			// 从容器获取名称为 localeResolver 类型为 LocaleResolver 的策略组件
			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Detected " + this.localeResolver);
			}
			else if (logger.isDebugEnabled()) {
				logger.debug("Detected " + this.localeResolver.getClass().getSimpleName());
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			// 如果从容器获取指定组件失败,则创建并使用缺省组件
			this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No LocaleResolver '" + LOCALE_RESOLVER_BEAN_NAME +
						"': using default [" + this.localeResolver.getClass().getSimpleName() + "]");
			}
		}
	}

方法 #getDefaultStrategies

该方法使用指定的策略接口 strategyInterface 创建一组策略对象。上面的方法initLocaleResolver就是使用该方法创建了一个缺省的LocaleResolver策略对象。

该方法会使用DispatcherServlet缺省配置文件DispatcherServlet.properties获取缺省要使用的策略实现类。

	/**
	 * Create a List of default strategy objects for the given strategy interface.
	 * The default implementation uses the "DispatcherServlet.properties" file (in the same
	 * package as the DispatcherServlet class) to determine the class names. It instantiates
	 * the strategy objects through the context's BeanFactory.
	 * @param context the current WebApplicationContext
	 * @param strategyInterface the strategy interface
	 * @return the List of corresponding strategy objects
	 */
	@SuppressWarnings("unchecked")
	protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
		 // 策略接口长名称作为 key
		String key = strategyInterface.getName();
		// 这里 defaultStrategies 是一个类静态属性,指向classpath resource 文件 DispatcherServlet.properties
		// 该行获取策略接口对应的实现类,是','分割的实现类的长名称
		String value = defaultStrategies.getProperty(key);
		if (value != null) {
          // 
			String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
			List<T> strategies = new ArrayList<>(classNames.length);
			for (String className : classNames) {
				try {
					// 获取策略接口实现类
					Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
					// 创建该策略接口实现类的对象
					Object strategy = createDefaultStrategy(context, clazz);
					strategies.add((T) strategy);
				}
				catch (ClassNotFoundException ex) {
					throw new BeanInitializationException(
							"Could not find DispatcherServlet's default strategy class [" + className +
							"] for interface [" + key + "]", ex);
				}
				catch (LinkageError err) {
					throw new BeanInitializationException(
							"Unresolvable class definition for DispatcherServlet's default strategy class [" +
							className + "] for interface [" + key + "]", err);
				}
			}
			return strategies;
		}
		else {
			return new LinkedList<>();
		}
	}

方法 #createDefaultStrategy

该方法使用AutowireCapableBeanFactory#createBean创建策略实现类的一个实例对象。

	 /**
	 * Create a default strategy.
	 * The default implementation uses
	 * org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean.
	 * @param context the current WebApplicationContext
	 * @param clazz the strategy implementation class to instantiate
	 * @return the fully configured strategy instance
	 * @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()
	 * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean
	 */
	protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
		return context.getAutowireCapableBeanFactory().createBean(clazz);
	}

文件DispatcherServlet.properties

文件DispatcherServlet.properties是一个属性文件。每个属性的key是一个策略接口的长名称,而valuekey指定的策略接口的多个实现类的长名称,每个类名称之间使用,分割。

该文件位于包org.springframework.web.servlet,和DispatcherServlet在同一个pacakge路径下面。具体内容如下 :

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

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
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐