DispatcherServlet的初始化,是在org.springframework.web.context.ContextLoaderListener完成加载后,才开始的。这时候WebApplicationContext(包含DAO,Service等)已经初始完毕。
DispatcherServlet的初始过程主要完成
1.WebApplicationContext父子容器维护
2.初始化Servlet策略
本文主要内容
DispatcherServlet的集成体系
DispatcherServlet初始化过程
1.DispatcherServlet的继承体系
DispatcherServlet是个普通servlet,是访问入口。明白了继承体系,方便梳理初始化模板。
2.DispatcherServlet初始化过程
2.1 init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
final
void
init()
throws
ServletException {
// Set bean properties from init parameters.
//将Servlet配置的参数封装到pvs变量中
try
{
PropertyValues pvs =
new
ServletConfigPropertyValues(getServletConfig(),
this
.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(
this
);
ResourceLoader resourceLoader =
new
ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.
class
,
new
ResourceEditor(resourceLoader));
initBeanWrapper(bw);
//bw就是DispatcherServlet
bw.setPropertyValues(pvs,
true
);
}
// 让子类实现
initServletBean();
if
(logger.isDebugEnabled()) {
logger.debug(
"Servlet '"
+ getServletName() +
"' configured successfully"
);
}
}
|
2.2 initServletBean方法
1
2
3
4
5
|
protected
final
void
initServletBean()
throws
ServletException {
this
.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
//子类可以实现
}
|
初始化webApplicationContext ;初始化FrameworkServlet
2.3 initWebApplicationContext方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
protected
WebApplicationContext initWebApplicationContext() {
WebApplicationContext wac = findWebApplicationContext();
if
(wac ==
null
) {
// No fixed context defined for this servlet - create a local one.
WebApplicationContext parent =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
wac = createWebApplicationContext(parent);
}
if
(!
this
.refreshEventReceived) {
// Apparently not a ConfigurableApplicationContext with refresh support:
// triggering initial onRefresh manually here.
onRefresh(wac);
////调用DispatcherServlet.initStrategies入口
}
if
(
this
.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
...
}
}
return
wac;
}
protected
WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class<?> contextClass = getContextClass();
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
//维护双亲委派
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
wac.setConfigLocation(getContextConfigLocation());
//调用DispatcherServlet.initStrategies入口
wac.addApplicationListener(
new
SourceFilteringListener(wac,
new
ContextRefreshListener()));
postProcessWebApplicationContext(wac);
wac.refresh();
return
wac;
}
private
class
ContextRefreshListener
implements
ApplicationListener<ContextRefreshedEvent> {
public
void
onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.
this
.onApplicationEvent(event);
}
}
|
2.5.initStrategies方法
1
2
3
4
5
6
7
8
9
10
|
protected
void
initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
}
|
初始化9个组件。
初始化组件过程,大体都是先从容器中获取,获取不到,则调用getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface)方法。
默认配置来自DispatcherServlet.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
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
|
2.6.initHandlerMappings方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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.
OrderComparator.sort(
this
.handlerMappings);
}
}
else
{
...
}
}
}
|
将spring mvc容器中HandlerMapping对象赋给handlerMappings 列表。这些对象都是在标签解析时,自动加载入容器中的。具体<SpringMVC源码分析(1)标签解析>
2.7 initHandlerAdapters方法
与initHandlerMappings思路完全一致。
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1877958,如需转载请自行联系原作者