在上一篇文章Spring与MVC(一)中,我们配置了一个最基本的Web应用,这一章我们来看看这个最基本的Web应用是如何创建DispatcherServlet和ContextLoaderListener的。
SpringServletContainerInitializer
在Servlet 3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果能发现的话,就会用它来配置Servlet容器。
Spring提供了这个接口的实现,名为SpringServletContainerInitializer,这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。Spring 3.2引入了一个便利的WebApplicationInitializer基础实现,也就是AbstractAnnotationConfigDispatcherServletInitializer。因为我们扩展了AbstractAnnotationConfigDispatcherServletInitializer(同时也就是实现了WebApplicationInitializer),因此当部署到Servlet 3.0容器中的时候,容器会自动发现它,并用它来配置Servlet上下文。
SpringServletContainerInitializer实现了ServletContainerInitializer接口唯一的一个方法:onStartup。在该方法中,寻找所有实现了WebApplicationInitializer接口的配置类,然后根据@Order注解指定的顺序依次调用我们配置类的onStartup方法。
AbstractAnnotationConfigDispatcherServletInitializer的基础关系:

调用AbstractDispatcherServletInitializer.onStartup方法:
1 |
|
创建ContextLoaderListener
首先调用父类AbstractContextLoaderInitializer的onStartup方法:
1 |
|
首先调用AbstractAnnotationConfigDispatcherServletInitializer.createRootApplicationContext创建一个AnnotationConfigWebApplicationContext:
1 | protected WebApplicationContext createRootApplicationContext() { |
其中getRootConfigClasses方法我们在WebAppInitializer重写了,返回的是RootConfig.class。接着新建一个AnnotationConfigWebApplicationContext,将RootConfig.class注册到AnnotationConfigWebApplicationContext的annotatedClasses中。
回到AbstractContextLoaderInitializer.registerContextLoaderListener,创建一个ContextLoaderListener,将createRootApplicationContext返回的AnnotationConfigWebApplicationContext赋值给ContextLoaderListener的context中。
将刚才创建的ContextLoaderListener添加到ServletContext中。
创建DispatcherServlet
回到AbstractDispatcherServletInitializer.onStartup,创建完ContextLoaderListener之后,调用registerDispatcherServlet注册DispatcherServlet:
1 | protected void registerDispatcherServlet(ServletContext servletContext) { |
首先调用getServletName()方法,获取servletName,默认为”dispatcher”。
调用AbstractAnnotationConfigDispatcherServletInitializer.createServletApplicationContext,创建AnnotationConfigWebApplicationContext:
1 | protected WebApplicationContext createServletApplicationContext() { |
首先创建AnnotationConfigWebApplicationContext。再调用getServletConfigClasses方法获取配置,该方法在WebAppInitializer中被重写,返回WebConfig.class。然后注册到AnnotationConfigWebApplicationContext的annotatedClasses中。
回到AbstractDispatcherServletInitializer.registerDispatcherServlet方法,调用createDispatcherServlet创建DispatcherServlet。
将我们创建的DispatcherServlet添加到servletContext中。在registration中添加Servlet映射,Servlet映射由我们的WebAppInitializer配置类指定。
获取过滤器,注册到servletContext中。
总结
我们可以看到在AbstractDispatcherServletInitializer.onStartup中:
- 通过
super.onStartup(servletContext)方法创建ContextLoaderListener。getRootConfigClasses方法返回的带有@Configuration注解的类将会用来配置ContextLoaderListener创建的应用上下文中的bean。 - 通过
registerDispatcherServlet(servletContext)方法创建DispatcherServlet。getServletConfigClasses方法返回的带有@Configuration注解的类将会用来配置DispatcherServlet应用上下文中的bean。