1.根据servlet3.0约定,提供Web服务的框架,必须实现ServletContainerInitializer接口,重写onStartUp方法。Spring根据约定,提供了ServletContainerInitializer接口的子接口SpringServletContainerInitializer。
2.在Spring根据SpringServletContainerInitializer接口的实现类在配置Web环境时,又向我们甩出了WebApplicationInitializer接口,用于我们做具体的配置(SpringMVC,Spring的核心配置,以及监听器,过滤器等等)。在WebApplicationInitializer接口下又提供了AbstractContextLoaderInitializer抽象子类,主要用于在服务器启动时注册ContextLoaderListener监听器,用于加载关于Spring核心配置相关的配置类信息,创建ROOT WebApplicationContext容器。,具体代码如下(AbstractContextLoaderInitializer类部分源码):
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
}
}
3.在AbstractContextLoaderInitializer抽象子类下又提供了AbstractDispatcherServletInitializer抽象子类。在AbstractDispatcherServletInitializer类的onStartUp方法中主要提供了DispatcherServlet(核心控制器)的创建方法(用于创建Servlet WebApplicationContext容器—SpringMVC核心配置容器),以及过滤器的注入。
public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
/**
* The default servlet name. Can be customized by overriding {@link #getServletName}.
*/
public static final String DEFAULT_SERVLET_NAME = "dispatcher";
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
}
}
4.针对Root WebApplicationContext与Servlet WebApplicationContext两个容器的具体配置信息的提供,spring又向我们提供了AbstractAnnotationConfigDispatcherServletInitializer,即我们实现SpringMVCP配置类的需要继承实现的最终抽象类,在AbstractAnnotationConfigDispatcherServletInitializer类中主要提供了我们SpringMVC配置(getServletConfigClasses),Spring配置(getRootConfigClasses),Dispatcher映射关系(getServletMappings)的配置信息的提交方法。
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
extends AbstractDispatcherServletInitializer {
/**
* {@inheritDoc}
* <p>This implementation creates an {@link AnnotationConfigWebApplicationContext},
* providing it the annotated classes returned by {@link #getRootConfigClasses()}.
* Returns {@code null} if {@link #getRootConfigClasses()} returns {@code null}.
*/
@Override
@Nullable
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(configClasses);
return context;
}
else {
return null;
}
}
/**
* {@inheritDoc}
* <p>This implementation creates an {@link AnnotationConfigWebApplicationContext},
* providing it the annotated classes returned by {@link #getServletConfigClasses()}.
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
context.register(configClasses);
}
return context;
}
/**
* Specify {@code @Configuration} and/or {@code @Component} classes for the
* {@linkplain #createRootApplicationContext() root application context}.
* @return the configuration for the root application context, or {@code null}
* if creation and registration of a root context is not desired
*/
@Nullable
protected abstract Class<?>[] getRootConfigClasses();
/**
* Specify {@code @Configuration} and/or {@code @Component} classes for the
* {@linkplain #createServletApplicationContext() Servlet application context}.
* @return the configuration for the Servlet application context, or
* {@code null} if all configuration is specified through root config classes.
*/
@Nullable
protected abstract Class<?>[] getServletConfigClasses();
}
5.综上:在相应方法中提交相应配置信息后,Tomcat服务器在启动时,会追层调用各个子类的onStartUp()方法,先完成Root WebApplicationContext容器的创建及配置,再完成Servlet WebApplicationContext容器的创建及配置。