Spring MVC DispatcherServlet 策略初始化 -- initLocaleResolver
本文所用源代码基于 Spring Web MVC 5.1.4.RELEASE概述DispatcherServlet#initLocaleResolver方法用于准备DispatcherServlet处理请求时所使用的LocaleResolver策略组件对象。#initLocaleResolver首先尝试从容器(及其祖先容器)获取名称为localeResolver的bean组件对象,记录到...
本文所用源代码基于
Spring Web MVC 5.1.4.RELEASE
概述
DispatcherServlet#initLocaleResolver
方法用于准备DispatcherServlet
处理请求时所使用的LocaleResolver
策略组件对象。
#initLocaleResolver
首先尝试从容器(及其祖先容器)获取名称为localeResolver
的bean
组件对象,记录到DispatcherServlet
实例成员属性localeResolver
。如果容器中名称为localeResolver
的bean
组件不存在,则创建缺省的LocaleResolver
对象记录到localeResolver
。
根据上面大致的介绍,我们可以看出:
DispatcherServlet
优先使用注册到容器中名为localeResolver
的LocaleResolver
策略组件。利用这一特性,开发人员可以注册一个自定义的LocaleResolver
,但必须使用名称localeResolver
。DispatcherServlet
的属性localeResolver
总是会对应一个LocaleResolver
策略组件,如果容器中名称为localeResolver
的组件不存在,则DispatcherServlet
会缺省创建一个LocaleResolver
供使用。
基于
@EnableWebMvc
+Java Config
的Spring 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
是一个策略接口的长名称,而value
是key
指定的策略接口的多个实现类的长名称,每个类名称之间使用,
分割。
该文件位于包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
更多推荐
所有评论(0)