SpringMVC之容器的创建

SpringMVC之ServletContainerInitializer和WebApplicationInitializer

首先项目需要放在web容器中启动。例如:tomcat,jetty

容器启动时先去加载META-INF/services/javax.servlet.ServletContainerInitializer文件下写的指定类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OpudzUUj-1644830105026)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220214152134761.png)]
在这里插入图片描述
ServletContainerInitializer基于服务提供者接口(SPI)概念,是web容器启动时提供给第三方组件的接口。是 Servlet 3.0 新增的一个接口。Servlet3.0的Web应用服务器中,服务器会查找实现类,执行实现类的onStartup方法用于配置Servlet容器例如注册Servlet、Filter或Listener,以取代通过web.xml配置注册。这样就利于开发内聚的web应用框架。

@Override
	public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						//实例化WebApplicationInitializer子类
						initializers.add((WebApplicationInitializer)
								ReflectionUtils.accessibleConstructor(waiClass).newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}

SpringServletContainerInitializer中实现了ServletContainerInitializer的onStartup方法。可以看到方法中有两个参数

public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
如果ServletContainerInitializer接口的实现类使用@HandlesTypes注解声明了感兴趣的类或接口, 那么这个感兴趣的类及其子类或接口的实现类就会被设置到Set<Class<?>> webAppInitializerClasses中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jJkrcgjQ-1644830105028)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220214155251577.png)]

因此,ServletContainerInitializer和WebApplicationInitializer的关系为:spring实现web服务器提供的类,实现类为SpringServletContainerInitializer,再通过把WebApplicationInitializer的实现类作为参数,从而进行实例化对spring容器的加载

WebApplicationInitializer相当于web.xml,可以在其实现类中注册Servlet、Filter或Listener等操作

在WebApplicationInitializer的子类中使用AbstractAnnotationConfigDispatcherServletInitializer来配置,它会i加载DispatcherServlet、ContextLoaderListener、根容器、IOC容器,真正实现不再需要使用web.xml
在这里插入图片描述
在这里插入图片描述
createServletApplicationContext:创建web的ioc容器,主要用于用于和该Servlet相关的一些组件,比如Controller、ViewResovler等;

createRootApplicationContext:创建根容器,整个Web应用程序需要共享的一些组件,比如DAO、数据库的ConnectionFactory等

DispatcherServlet:把ioc容器放入其属性中,这样这样我们只要得到Servlet就可以得到WebApplicationContext对象,并利用这个对象访问spring容器管理的bean。
ContextLoaderListener:把ioc容器放入其属性中
在这里插入图片描述


版权声明:本文为yan_pan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。