在上一篇文章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。