纯注解的mvc 如何去掉web.xml
在 servlet 中有一个规范,就是当 servlet 容器启动的时候会根据 spi 规范加载
META-INF/services 文件夹下面的 javax.servlet.ServletContainerInitializer 文件,该文件下面的
类会实现 javax.servlet.ServletContainerInitializer 接口。如图:
![](https://oscimg.oschina.net/oscnet/up-9494e42c8884379072d680a8e8eea98dc8a.png)
![](https://oscimg.oschina.net/oscnet/up-e54cfb82c8271619141ea3d0e683cd2ac6c.png)
该类在启动的时候会被 servlet 容器实例化,然后调用 onStartup 方法,并且 servlet 容
器会收集实现了@HandlesTypes 注解里面的接口的类,并且做为入参传入到 onStartup 方法
中,我们拿到 set 容器中的类就可以反射调用接口里面的方法了,这是 servlet 规范,该规范
就能保证 servlet 容器在启动的时候就会完成这些操作。Springmvc 就借助这一点完成了取代
web.xml 的工作。
在 springmvc 中,spring-web jar 包下面也会有一个 javax.servlet.ServletContainerInitializer
文件,如图:
![](https://oscimg.oschina.net/oscnet/up-55ac88017d8a9e3b21b8a7140c57d6c4794.png)
![](https://oscimg.oschina.net/oscnet/up-65478ebdeae4b8a3b3e13ebfd992cd68686.png)
Tomcat 就会加载这个类,调用其 onStartup 方法。
![](https://oscimg.oschina.net/oscnet/up-221c9d29fe87ae32d85e10c47915b87db5d.png)
收集的是实现了 WebApplicationInitializer 接口的类,在 springmvc 工程中我们自己写了
这么一个类,如图:
![](https://oscimg.oschina.net/oscnet/up-8e8d090e94ca2ed23a830acefe179ceb314.png)
该类的父类最终会实现 WebApplicationInitializer,所以该类的父类必定会有一个
onStartup 方法。其父类截图如下:
![](https://oscimg.oschina.net/oscnet/up-21f15b5890a5cfb0406aab3773509b1b22f.png)
1、super.onStartup 完成了实例化 listener 的工作
![](https://oscimg.oschina.net/oscnet/up-4fef03f51e929f7f60dd1f26928f59810c2.png)
这些代码功能就类似于在 web.xml 配置了 ContextLoaderListener,做了几个事情,1 创建了
上下文对象,如图:
![](https://oscimg.oschina.net/oscnet/up-cc784a2fb5f16dfd32b234d01a1c90e72eb.png)
这个上下文对象就是基于注解扫描的上下文对象,所以用这个上下文是需要注册一个类进
去,这个类就是用钩子方法调用到了自己写的方法。
![](https://oscimg.oschina.net/oscnet/up-f5b755f46dbadded98a0e91006e68e6a15f.png)
在钩子方法中获取到的类 springContainer 就会去扫描基本包,有@ComponentScan 注解,如
![](https://oscimg.oschina.net/oscnet/up-6a1552e945329c3ee0cebdb61c15162fddf.png)
通过钩子方法获取到扫描类后,注册到了上下文对象中,然后把 spring 的上下文对象设置到
了 ContextLoaderListener 监听器对象中,最后把监听器对象设置到了 servletContext 中。这
里上下文对象还没有调用 refresh 方法完成 spring 的启动。
2、registerDispatcherServlet(servletContext);完成了实例化 DispatcherServlet
![](https://oscimg.oschina.net/oscnet/up-c472e9c5e0f654f2361068573062de10783.png)
步骤跟创建监听器差不多,创建上下文对象,跟上面差不多,创建 dispatcherServlet
对象,把 servlet 对象加入到 servletContext 上下文中。把上下文对象设置到了
dispatcherServlet 对象中了,这里上下文对象还没有调用 refresh 方法,没有启动
spring 容器。