我是靠谱客的博主 义气缘分,最近开发中收集的这篇文章主要介绍web容器启动Spring应用程序原理,@HandlesTypes与ServletContainerInitializer,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

查看Spring源码发现有如下东西:
在这里插入图片描述

ServletContainerInitializer接口

在这里插入图片描述
首先我们要知道这是个Java EE规范中的接口,由具体的Servlet容器来实现,在Web容器启动时被回调。

作用

类似于一个监听容器启动的监听器。

用法

在实现该接口后,需要在SPI文件中注册,在Servlet容器启动时通过SPI从classpath下查找其实现类,实例化后进行回调。
在这里插入图片描述

举例

Spring的实现类
在这里插入图片描述

那实现类上标注了@HandlesTypes注解又是干嘛的呢?

@HandlesTypes注解

在这里插入图片描述

含义

这也是Java EE规范中的注解,表示当前ServletContainerInitializer的实现类,能处理的类型。这两个都是Servlet3.0中的东西。

主要作用

Servlet容器(例如tomcat)启动时,会将SPI注册的Java EE接口ServletContainerInitializer的所有的实现类(例如,SpringServletContainerInitializer)挨个回调其onStartup方法。

而onStartup方法是需要参数的,这时@HandlesTypes就派上用场了。

onStartup方法所需要的参数就通过@HandlesTypes注解传入。

实现原理

@HandlesTypes注解由Servlet容器提供支持(实现),参数中指定的所有实现类,利用字节码扫描框架(例如ASM、BCEL)从classpath中扫描出来,放入集合,传给回调方法onStartup的第一个参数。

言归正传,为什么Spring需要用到这部分注解?

我们总是能在传统的Spring项目看到如下Web容器配置文件。
在这里插入图片描述
为什么Spring项目中没有web配置文件?

通过创建Web初始化类,继承自AbstractAnnotationConfigDispatcherServletInitializer

去除web.xml配置文件的实现原理就得依靠Java EE提供的@HandlesTypes与ServletContainerInitializer了。

因此,Spring中使用该注解和接口的原因之一就是去除配置文件。

Spring去除配置文件的实现原理

有请看@HandlesTypes中参数WebApplicationInitializer的某个Spring-webmvc中的实现类:AbstractDispatcherServletInitializer。
在这里插入图片描述

注意:如果是SpringBoot项目这里就是唯一容器上下文。如果项目是SpringMVC+Spring,这里创建的上下文是Spring容器的子上下文,组成父子上下文。父子上下文特点是子容器(controller层)可访问父容器(service层,dao层)里的Bean,父容器不能访问子容器里的Bean,优点是层次分明。像是这种父子结构的容器,在@Service层是不能注入@Controller Bean的,原因如上。

因此我们得出结论,spring是通过代码中配置从而去除的web配置文件。

启动流程

假设Servlet容器是tomcat。

  1. 由tomcat在启动时根据SPI机制的ServiceLoader#load方法拿到所有JavaEE接口(ServletContainerInitializer)注册的实现类。
  2. Spring对该接口的实现类是SpringServletContainerInitializer,其类上标注了@HandlesTypes({WebApplicationInitializer.class})。
  3. tomcat从classpath下找到所有的WebApplicationInitializer实现类,将所有的实现类传入SpringServletContainerInitializer#onStartup方法的第一个参数,调用方法。
  4. 回到SpringServletContainerInitializer#onStartup方法中的逻辑,将所有的WebApplicationInitializer实现类的onStartup方法一一调用。
  5. WebApplicationInitializer的实现类之一是AbstractDispatcherServletInitializer,会创建spring容器、配置web.xml、注册过滤器。

    当存在多个WebApplicationContext会设置其层级关系。

编写代码测试

理论与实践相结合,利用tomcat + @HandlesTypes与ServletContainerInitializer + Spring-webmvc模拟SpringBoot去除web.xml启动。

代码地址:https://github.com/lmmarisej/light-springboot。

最后

以上就是义气缘分为你收集整理的web容器启动Spring应用程序原理,@HandlesTypes与ServletContainerInitializer的全部内容,希望文章能够帮你解决web容器启动Spring应用程序原理,@HandlesTypes与ServletContainerInitializer所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部