容器启动,会扫描web.xml文件;扫描到配置的spring的listener时就初始化spring容器;
扫描到DispacthServlet时就初始化该Servlet;初始化Servlet调用init()方法,该方法的实现是在父类HttpServletBean中;继承关系如下:
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// Set bean properties from init parameters.
try {
//根据ServletConfig读取配置信息
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
//把DispacthServlet本身传递给工厂类,生成BeanWrapper实例供IoC容器管理
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
//获取资源加载类
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
//空实现
initBeanWrapper(bw);
//把得到的配置信息给DispacthServlet
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
}
//继续初始化,由子类实现。具体在FrameworkServlet中
// Let subclasses do whatever initialization they like.
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
/**
* Overridden method of {@link HttpServletBean}, invoked after any bean properties
*覆盖方法,在配置属性信息后执行;生成DispacthServlet的WebApplicationContext容器;
* have been set. Creates this servlet's WebApplicationContext.
*/
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();//用于记录初始时间
try {
//这个其实就是根据当前的ServletContext获取spring容器,容器初始化成功后会放入ServletContext中;
//并标示为WebApplicationContext.ROOT;或者是FrameworkServlet的构造函数中已经传入WebApplicationContext容器;
//期间调用onRefresh(..)方法,刷新IoC容器;
//如果是根据ServletContext中得到的容器,则会根据该容器生成新的容器,并把ServletContext中的容器设为父容器;
//生成的容器类型指定为:XmlWebApplicationContext.class;
//在刷新容器的同时也会初始化DispacthServlet;
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
elapsedTime + " ms");
}
}
/**
*该类在FrameworkServlet内部;由适配的方式调用到该类中的onApplicationEvent
* ApplicationListener endpoint that receives events from this servlet's WebApplicationContext
* only, delegating to <code>onApplicationEvent</code> on the FrameworkServlet instance.
*/
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
//调用外部类FrameworkServlet中的onApplicationEvent方法;
FrameworkServlet.this.onApplicationEvent(event);
}
}
/**
* Callback that receives refresh events from this servlet's WebApplicationContext.
* <p>The default implementation calls {@link #onRefresh},
* triggering a refresh of this servlet's context-dependent state.
* @param event the incoming ApplicationContext event
*/
public void onApplicationEvent(ContextRefreshedEvent event) {
//刷新容器期间,以事件的方式初始化DispatchServlet;
this.refreshEventReceived = true;//标示
//这个由DispatchServlet实现
onRefresh(event.getApplicationContext());
}
/**
* This implementation calls {@link #initStrategies}.
*/
@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);
//根据org.springframework.web.servlet.HandlerMapping去IoC容器中查找
//初始化HandlerMappings集合,并待排序
//可能得到的两个值是RequestMappingHandlerMapping
//和BeanNameUrlHandlerMapping
//这两个类中都有一个LinkedHashMap类型的handerMethods属性
//保存着该类型下的说有映射路径及相关参数,该属性从
//AbstractHandlerMethodMapping继承而来;
initHandlerMappings(context);
//根据org.springframework.web.servlet.HandlerAdapter去IoC容器中查找
//能得到RequestMappingHandlerAdapter
//HttpRequestHandlerAdapter
//SimpleControllerHandlerAdapter
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
这里又点疑惑:RequestMappingHandlerMapping得到的时候已经有系统中所有的映射路径了,这个是什么时候初始化到该对象中的呢;