注:SpringFramework的版本是4.3.x。
图1 DispatchServlet的类继承图
调用Servlet的init方法初始化Servlet,时序图如下所示:
图2 调用Servlet的init的时序图
这个init(...)是Servlet的方法,在容器container初始化Servlet时调会调用Servlet的init(...)方法。DispatcherServlet中通过init(...)来生成需要的webApplicationContext。
图2中步骤6中的onRefresh(...)的实现在DispatcherServlet中实现,源码如下List-1所示,initStrategies方法中对DispatcherServlet的属性进行了初始化。
List-1 DispatcherServlet的onRefresh方法中的源码
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
着重来看下方法initHandlerMappings的实现,方法中的源码如下List-2所示
List-2 initHandlerMappings方法的源码
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<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");
}
}
}
对LIst-2的说明:
来分析getDefaultStrategies的源码,如下List-3所示。
List-3 getDefaultStrategies的源码
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<T>(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(
"Error loading DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]: problem with class file or dependent class", err);
}
}
return strategies;
}
else {
return new LinkedList<T>();
}
}
defaultStrategies是DispatcherServlet的一个属性,它的初始化如下List-4所示,
List-4 defaultStrategies的初始化源码
private static final Properties defaultStrategies;
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
DEFAULT_STRATEGIES_PATH的值是DispatcherServlet.properties,我们来看下这个文件里面的内容,如下图3所示,可以看到默认情况下HandlerMapping定义了俩个,即BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping,所以List-3中的createDefaultStrategy方法会将BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping创建为bean,并注册到applicationContext中。
图3 文件DispatcherServlet.properties的内容
List-3中的createDefaultStrategy(context, clazz),代码如下List-4所示。通过ApplicationContext和Class<?>,就可以创建bean了,这种手动创建的方式可以学习下。
List-4 方法createDefaultStrategy的源码
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
return context.getAutowireCapableBeanFactory().createBean(clazz);
}
(adsbygoogle = window.adsbygoogle || []).push({});