昨晚有人提到spring的最初版本interface21,Spring的源码太复杂,跟着看有点晕,所以决定跟着人家的博客,先走一下interface21中DispatcherServlet初始化的流程。看完了从人家的编码风格和逻辑跳转,收获满满。
1:首先,执行DispatcherServlet的父类HttpServletBean的init方法;
public final void init() throws ServletException {
this.identifier = "Servlet with name '" + getServletConfig().getServletName() + "' ";
logger.info(getIdentifier() + "entering init...");
// Set bean properties
try {
//servlet 初始化属性值
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), requiredProperties);
BeanWrapper bw = new BeanWrapperImpl(this);
//为BeanWrapperImpl设置属性。
bw.setPropertyValues(pvs);
logger.debug(getIdentifier() + "properties bound OK");
// Let subclasses do whatever initialization they like
initServletBean();
logger.info(getIdentifier() + "configured successfully");
} catch (BeansException ex) {
String mesg = getIdentifier() + ": error setting properties from ServletConfig";
logger.error(mesg, ex);
throw new ServletException(mesg, ex);
} catch (Throwable t) {
// Let subclasses throw unchecked exceptions
String mesg = getIdentifier() + ": initialization error";
logger.error(mesg, t);
throw new ServletException(mesg, t);
}
}
2. 获取Servlet的初始化参数,创建BeanWrapperImpl 实例,设置属性值;
3.执行HttpServletBean的子类FrameworkServlet的initServletBean方法;
protected final void initServletBean() throws ServletException {
long startTime = System.currentTimeMillis();
logger.info("Framework servlet '" + getServletName() + "' init");
this.webApplicationContext = createWebApplicationContext();
initFrameworkServlet();
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Framework servlet '" + getServletName() + "' init completed in " + elapsedTime + " ms");
}
4.调用FrameworkServlet的createWebApplicationContext方法.
private WebApplicationContext createWebApplicationContext() throws ServletException {
getServletContext().log("Loading WebApplicationContext for servlet '" + getServletName() + "'");
ServletContext sc = getServletConfig().getServletContext();
WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(sc);
String namespace = getNamespace();
//这段代码风格上有点东西
WebApplicationContext waca = (this.contextClass != null) ?
instantiateCustomWebApplicationContext(this.contextClass, parent, namespace) :
new XmlWebApplicationContext(parent, namespace);
logger.info("Loading WebApplicationContext for servlet '" + getServletName() + "': using context class '" + waca.getClass().getName() + "'");
waca.setServletContext(sc);
if (this.publishContext) {
// Publish the context as a servlet context attribute
String attName = getServletContextAttributeName();
sc.setAttribute(attName, waca);
logger.info("Bound context of servlet '" + getServletName() + "' in global ServletContext with name '" + attName + "'");
}
return waca;
}
5.进入createWebApplicationContext方法,从ServletContext的属性中获取WebApplicationContext,该上下文是由ContextLoaderListener加载的。
6.执行子上下文XmlWebApplicationContext的waca.setServletContext方法,去加载petclinic-servlet.xml配置文件(国际化,主题,HandlerMapping、HandlerAdapter、视图解析等相关配置)。
7.将该子上下文设置到ServletContext属性中
8.进入DispatcherServlet类的initFrameworkServlet方法,主要执行一些初始化工作
protected void initFrameworkServlet() throws ServletException {
initLocaleResolver();
initThemeResolver();
initHandlerMappings();
initHandlerAdapters();
initViewResolver();
}
9.国际化相关:执行initLocaleResolver方法,从上下文中获取localeResolver bean,没有则使用默认AcceptHeaderLocaleResolver
private void initLocaleResolver() throws ServletException {
try {
this.localeResolver = (LocaleResolver) getWebApplicationContext().getBean(LOCALE_RESOLVER_BEAN_NAME);
logger.info("Loaded locale resolver [" + this.localeResolver + "]");
} catch (NoSuchBeanDefinitionException ex) {
// We need to use the default
this.localeResolver = new AcceptHeaderLocaleResolver();
logger.info("Unable to locate locale resolver with name '" + LOCALE_RESOLVER_BEAN_NAME + "': using default [" + this.localeResolver + "]");
} catch (BeansException ex) {
// We tried and failed to load the LocaleResolver specified by a bean
throw new ServletException("Fatal error loading locale resolver with name '" + LOCALE_RESOLVER_BEAN_NAME + "': using default", ex);
}
}
10.主题相关:执行initThemeResolver方法,从上下文中获取themeResolver bean,没有则使用默认FixedThemeResolver
private void initThemeResolver() throws ServletException {
try {
this.themeResolver = (ThemeResolver) getWebApplicationContext().getBean(THEME_RESOLVER_BEAN_NAME);
logger.info("Loaded theme resolver [" + this.themeResolver + "]");
} catch (NoSuchBeanDefinitionException ex) {
// We need to use the default
this.themeResolver = new FixedThemeResolver();
logger.info("Unable to locate theme resolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" + this.themeResolver + "]");
} catch (BeansException ex) {
// We tried and failed to load the ThemeResolver specified by a bean
throw new ServletException("Fatal error loading theme resolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default", ex);
}
}
11.执行initHandlerMappings方法,从上下文中获取HandlerMapping类型的bean,没有则使用默认BeanNameUrlHandlerMapping
private void initHandlerMappings() throws ServletException {
this.handlerMappings = new ArrayList();
// Find all HandlerMappings in the ApplicationContext
String[] hms = getWebApplicationContext().getBeanDefinitionNames(HandlerMapping.class);
for (int i = 0; i < hms.length; i++) {
initHandlerMapping(hms[i]);
logger.info("Loaded handler mapping [" + hms[i] + "]");
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings.isEmpty()) {
initDefaultHandlerMapping();
logger.info("No HandlerMappings found in servlet '" + getServletName() + "': using default");
} else {
// We keep HandlerMappings in sorted order
Collections.sort(this.handlerMappings, new OrderComparator());
}
}
private void initDefaultHandlerMapping() throws ServletException {
try {
HandlerMapping hm = new BeanNameUrlHandlerMapping();
hm.setApplicationContext(getWebApplicationContext());
this.handlerMappings.add(hm);
} catch (ApplicationContextException ex) {
throw new ServletException("Error initializing default HandlerMapping: " + ex.getMessage(), ex);
}
}
12.执行initHandlerAdapters方法,从上下文中获取HandlerAdapter类型的bean,没有则使用默认SimpleControllerHandlerAdapter
private void initHandlerAdapters() throws ServletException {
this.handlerAdapters = new ArrayList();
String[] has = getWebApplicationContext().getBeanDefinitionNames(HandlerAdapter.class);
for (int i = 0; i < has.length; i++) {
initHandlerAdapter(has[i]);
logger.info("Loaded handler adapter [" + has[i] + "]");
}
// Ensure we have at least one HandlerAdapter, by registering
// a default HandlerAdapter if no other adapters are found.
if (this.handlerAdapters.isEmpty()) {
initDefaultHandlerAdapter();
logger.info("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
} else {
// We keep HandlerAdapters in sorted order
Collections.sort(this.handlerAdapters, new OrderComparator());
}
}
private void initDefaultHandlerAdapter() throws ServletException {
try {
HandlerAdapter ha = new SimpleControllerHandlerAdapter();
ha.setApplicationContext(getWebApplicationContext());
this.handlerAdapters.add(ha);
} catch (ApplicationContextException ex) {
throw new ServletException("Error initializing default HandlerAdapter: " + ex.getMessage(), ex);
}
}
13.执行initViewResolver方法,从上下文中获取viewResolver bean,没有则使用默认InternalResourceViewResolver
private void initViewResolver() throws ServletException {
try {
this.viewResolver = (ViewResolver) getWebApplicationContext().getBean(VIEW_RESOLVER_BEAN_NAME);
logger.info("Loaded view resolver [" + viewResolver + "]");
} catch (NoSuchBeanDefinitionException ex) {
// We need to use the default
this.viewResolver = new InternalResourceViewResolver();
try {
this.viewResolver.setApplicationContext(getWebApplicationContext());
} catch (ApplicationContextException ex2) {
throw new ServletException("Fatal error initializing default ViewResolver");
}
logger.info("Unable to locate view resolver with name '" + VIEW_RESOLVER_BEAN_NAME + "': using default [" + this.viewResolver + "]");
} catch (BeansException ex) {
// We tried and failed to load the ViewResolver specified by a bean
throw new ServletException("Fatal error loading view resolver: bean with name '" + VIEW_RESOLVER_BEAN_NAME + "' is required in servlet '" + getServletName() + "': using default", ex);
}
}
14.返回到FrameworkServlet类
15.返回到HttpServletBean类
16.Servlet的init方法执行完毕。