IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring与SpringMvc启动流程详解 -> 正文阅读

[Java知识库]Spring与SpringMvc启动流程详解

文章目录??

目录

文章目录??

前言

一、ServletContainerInitializer 接口是什么?

二、@HandlesTypes注解是什么

三、SpringServletContainerInitializer 是什么

四、WebApplicationInitializer 接口

总结




前言

本文不是SpringBoot的启动流程,是基于Tomcat,Spring,SpringMVC整合的启动流程,在我们启动Tomcat的时候Spring和SpringMvc是怎么加载启动的呢?ServletContainerInitializer 离不开这个关键的接口,围绕此接口在下文详细叙述。




一、ServletContainerInitializer 接口是什么?

在Tomcat容器启动的时候会扫描所有jar包中 META-INF/services 目录下存不存在一个名为javax.servlet.ServletContainerInitializer的文件,此文件的内容是实现了ServletContainerInitializer接口的实现类的全类名, 若存在则tomcat容器会将该实现类加载和实例化并调用该类的onStartup方法

public interface ServletContainerInitializer {
     void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;
}

可以看到onStartup方法有两个参数?

  1. ?Set<Class<?>> webAppInitializerClasses?是一个Class对象的Set集合,Set集合中的Class对象是从何而来呢?请带着问题向下接着看.
  2. ServletContext servletContex 
    

解答刚才提出的疑问,??参数一?webAppInitializerClasses?从何而来@HandlesTypes(WebApplicationInitializer.class), tomcat容器会扫描所有实现了注解标注的WebApplicationInitializer.class这个接口的实现类, 并把所有实现类的Class对象在调用onStartup方法时以参数的形式传递过来

二、@HandlesTypes注解是什么

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HandlesTypes {
    Class<?>[] value();
}

?这个注解标注接受一个Class的数组,这个数组会被当作参数传递给onStartup方法, 对应此方法的第一个参数, 这就解答了上面的问题,Set集合中的Class对象是从何而来的




三、SpringServletContainerInitializer 是什么

??在Spring中 (Spring的spi文件)org.springframework.web.SpringServletContainerInitializer 类就是实现了ServletContainerInitializer接口并重写了onStartup方法的实现类
?这时,当tomcat启动时就会调用SpringServletContainerInitializer 类重写的onStartup方法, Spring重写的onStartup方法就做了三件事

  1. 见图片2号方框判断条件, 找出所有非接口, 非抽象类 且是WebApplicationInitializer.class的子类的Class对象,
  2. 见图片3号方框, 把满足条件的所有Class生成的对象, 添加到List集合存储起来
  3. 见图片4号方框,?遍历第二步的集合中的对象 调用对象的onStartup方法,注意此处的onStartup方法是WebApplicationInitializer.class 这个接口定义的
    public interface WebApplicationInitializer {
    	void onStartup(ServletContext servletContext) throws ServletException;
    }

四、WebApplicationInitializer 接口

方便以编程方式配置ServletContext, Spring和SpringMvc容器的启动也依赖此接口及其子类, 主要依赖的子类有三个

  1. AbstractContextLoaderInitializer
  2. AbstractDispatcherServletInitializer
  3. AbstractAnnotationConfigDispatcherServletInitializer

类的继承结构如下:

?当调用onStartup方法时由其子类AbstractDispatcherServletInitializer#onStartup方法实现

//此处代码在AbstractDispatcherServletInitializer类中
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//此处调用父类的AbstractContextLoaderInitializer#onStartup方法
	super.onStartup(servletContext);//第一步
	registerDispatcherServlet(servletContext);//第二步
}

?第一步先调用了AbstractContextLoaderInitializer#onStartup方法

此处代码在AbstractContextLoaderInitializer类中
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
	registerContextLoaderListener(servletContext);
}

protected void registerContextLoaderListener(ServletContext servletContext) {
	WebApplicationContext rootAppContext = createRootApplicationContext();
	if (rootAppContext != null) {
		ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
		listener.setContextInitializers(getRootApplicationContextInitializers());
		servletContext.addListener(listener);
	}
}

?第二步紧接着调用AbstractDispatcherServletInitializer#registerDispatcherServlet

//此处代码在AbstractDispatcherServletInitializer类中
protected void registerDispatcherServlet(ServletContext servletContext) {
    String servletName = getServletName();
	WebApplicationContext servletAppContext = createServletApplicationContext();
	FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
    dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
    ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
    registration.setLoadOnStartup(1);
	registration.addMapping(getServletMappings());
	registration.setAsyncSupported(isAsyncSupported());
    Filter[] filters = getServletFilters();
	if (!ObjectUtils.isEmpty(filters)) {
		for (Filter filter : filters) {
			registerServletFilter(servletContext, filter);
		}
	}

	customizeRegistration(registration);
}




总结

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:12:16  更:2021-11-22 12:14:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:25:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码